rework #4
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: Steins7
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Code
|
||||
2. Specific Hardware used
|
||||
3. OS and toolchain
|
||||
4. Conditions for the bug to appear
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FEATURE]"
|
||||
labels: enhancement
|
||||
assignees: Steins7
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ bin
|
||||
.gdb_history
|
||||
*tags
|
||||
*.taghl
|
||||
.cache
|
||||
|
||||
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Steins7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
189
Makefile
189
Makefile
@ -1,189 +0,0 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# this GNU-makefile relies on the GCC toolchain
|
||||
|
||||
# --- control global project settings
|
||||
# RELEASE=1 -> enable optimisation, then disable debug
|
||||
# RELEASE=0 -> disable optimisation, then enable debug
|
||||
RELEASE=0
|
||||
|
||||
# --- project architecture
|
||||
# program name
|
||||
EXE_PREFIX=main
|
||||
# project folders, This Makefile should be in the same folder as the SRC folder
|
||||
SRC=src
|
||||
BIN=bin
|
||||
INC=include
|
||||
LIB=lib
|
||||
OBJ=${BIN}/obj
|
||||
DEP=${BIN}/dep
|
||||
# code folders, in the SRC folder
|
||||
SUBFOLDERS=drivers target
|
||||
# Define linker script file here
|
||||
LDSCRIPT=${SRC}/target/STM32F103XB.ld
|
||||
|
||||
# --- advanced config
|
||||
# List all user C define here
|
||||
UDEFS=
|
||||
# Define ASM defines here
|
||||
UADEFS=
|
||||
|
||||
# --- toolchain configuration
|
||||
TARGET=arm-none-eabi-
|
||||
CC=${TARGET}gcc
|
||||
CPP=${TARGET}g++
|
||||
OBJCOPY=${TARGET}objcopy
|
||||
AS=${TARGET}gcc -x assembler-with-cpp -c
|
||||
SIZE=${TARGET}size
|
||||
OBJDUMP=${TARGET}objdump
|
||||
|
||||
# --- hardware settings
|
||||
ARCH=armv7-m
|
||||
FLOAT-ABI=soft #no FPU on stm32f103
|
||||
CPU=cortex-m3
|
||||
CPUFLAGS=-mthumb
|
||||
FPU=fpv4-sp-d16 #"FLOAT-ABI=soft" disable that
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# --- makefile pre-incantation
|
||||
|
||||
# List all de:fault C defines here, like -D_DEBUG=1
|
||||
DDEFS=-march=${ARCH} -mfloat-abi=${FLOAT-ABI} -mcpu=${CPU} -mfpu=${FPU} $\
|
||||
${CPUFLAGS}
|
||||
# List all default ASM defines here, like -D_DEBUG=1
|
||||
DADEFS=-D__ASSEMBLY__
|
||||
|
||||
# --- deduce file names
|
||||
MAIN_C_FILES=${wildcard ${SRC}/${strip ${EXE_PREFIX}}*.c}
|
||||
MAIN_CPP_FILES=${wildcard ${SRC}/${strip ${EXE_PREFIX}}*.cpp}
|
||||
|
||||
COMMON_C_FILES=${filter-out ${MAIN_C_FILES},${wildcard ${SRC}/*.c}}
|
||||
COMMON_C_FILES+=${foreach dir,${SUBFOLDERS},${wildcard ${SRC}/${dir}/*.c}}
|
||||
|
||||
COMMON_CPP_FILES=${filter-out ${MAIN_CPP_FILES},${wildcard ${SRC}/*.cpp}}
|
||||
COMMON_CPP_FILES+=${foreach dir,${SUBFOLDERS},${wildcard ${SRC}/${dir}/*.cpp}}
|
||||
|
||||
COMMON_ASM_FILES=${foreach dir,${SUBFOLDERS},${wildcard ${SRC}/${dir}/*.s}}
|
||||
|
||||
MAIN_OBJECT_FILES=${sort ${patsubst ${src}/%.c,${obj}/%.o,${MAIN_C_FILES}} \
|
||||
${patsubst ${src}/%.cpp,${obj}/%.o,${MAIN_CPP_FILES}}}
|
||||
COMMON_OBJECT_FILES=${sort \
|
||||
${patsubst ${SRC}/%.c,${OBJ}/%.o,${COMMON_C_FILES}} \
|
||||
${patsubst ${SRC}/%.cpp,${OBJ}/%.o,${COMMON_CPP_FILES}} \
|
||||
${patsubst ${SRC}/%s,${OBJ}/%o,${COMMON_ASM_FILES}}}
|
||||
|
||||
LIBRARIES=${foreach dir,${wildcard ${LIB}/*},${wildcard ${LIB}/${dir}/*.a}}
|
||||
|
||||
OBJECT_FILES=${MAIN_OBJECT_FILES} ${COMMON_OBJECT_FILES}
|
||||
DEPEND_FILES=${OBJECT_FILES:%.o,%.d}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# --- makefile incantation
|
||||
# down here is black magic, you probably don't want to modify anything
|
||||
|
||||
DEFS=${DDEFS} ${UDEFS}
|
||||
ADEFS=${DADEFS} ${UADEFS}
|
||||
|
||||
# --- otpimisation
|
||||
ifeq (${strip ${RELEASE}},0)
|
||||
CFLAGS=-g3 -O0
|
||||
else
|
||||
CFLAGS=-O3
|
||||
endif
|
||||
|
||||
# --- c/cpp
|
||||
ifneq (${strip ${MAIN_CPP_FILES} ${COMMON_CPP_FILES}},)
|
||||
CC:=${CPP}
|
||||
CFLAGS+=-std=c++17
|
||||
else
|
||||
CFLAGS+=-std=c17
|
||||
endif
|
||||
|
||||
ASFLAGS=${LIB} $(DEFS) -Wa,--gdwarf2 $(ADEFS)
|
||||
CFLAGS+=-Wall ${DEFS} -Wextra -Warray-bounds -Wno-unused-parameter $\
|
||||
-fomit-frame-pointer
|
||||
LDFLAGS=-T ${LDSCRIPT} -lc -lgcc -lgcov -lm -Wl,-Map=$@.map,--gc-sections $\
|
||||
--specs=nosys.specs
|
||||
INCLUDE=-I ${INC}
|
||||
|
||||
# --- Generate dependency information
|
||||
CFLAGS+=-MD -MP -MF ${patsubst %o,%d,$@}
|
||||
ASFLAGS+=#-MD -MP -MF ${patsubst %o,%d,$@}
|
||||
|
||||
# --- folder tree
|
||||
DIR_GUARD=@mkdir -p ${@D}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# --- make rules
|
||||
all: ${BIN}/${EXE_PREFIX}.elf ${BIN}/${EXE_PREFIX}.hex ${BIN}/${EXE_PREFIX}.bin
|
||||
|
||||
rebuild : clean all
|
||||
|
||||
.SUFFIXES:
|
||||
.SECONDARY:
|
||||
.PHONY: all clean rebuild
|
||||
|
||||
# --- compiler command for elf file
|
||||
${BIN}/%.elf : ${MAIN_OBJECT_FILES} ${COMMON_OBJECT_FILES}
|
||||
@echo -e '\e[32;1m ==== linking $@ ====\e[0m'
|
||||
@echo ${COMMON_OBJECT_FILES}
|
||||
@echo
|
||||
${DIR_GUARD}
|
||||
${CC} ${INCLUDE} ${CFLAGS} -o $@ $^ ${LIBRARIES} ${LDFLAGS}
|
||||
${OBJDUMP} -h $@
|
||||
${SIZE} $@
|
||||
@echo
|
||||
|
||||
# --- compiler commands for uploadable files
|
||||
${BIN}/%.hex : ${BIN}/%.elf
|
||||
@echo -e '\e[33;1m ==== translating $< ====\e[0m'
|
||||
${OBJCOPY} -O ihex $< $@
|
||||
@echo
|
||||
|
||||
${BIN}/%.bin : ${BIN}/%.elf
|
||||
@echo -e '\e[33;1m ==== translating $< ====\e[0m'
|
||||
${OBJCOPY} -O binary $< $@
|
||||
@echo
|
||||
|
||||
# --- compiler commands for every source file
|
||||
${OBJ}/%.o : ${SRC}/%.cpp
|
||||
@echo -e '\e[36;1m ==== compiling $< ====\e[0m'
|
||||
${DIR_GUARD}
|
||||
${CPP} ${INCLUDE} -c ${CFLAGS} $< -o $@ ${LIBRARIES}
|
||||
@echo
|
||||
|
||||
${BIN}/%.o : ${SRC}/%.cpp
|
||||
@echo -e '\e[36;1m ==== compiling $< ====\e[0m'
|
||||
${DIR_GUARD}
|
||||
${CPP} ${INCLUDE} -c ${CFLAGS} $< -o $@ ${LIBRARIES}
|
||||
@echo
|
||||
|
||||
${OBJ}/%.o : ${SRC}/%.c
|
||||
@echo -e '\e[34;1m ==== compiling $< ====\e[0m'
|
||||
${DIR_GUARD}
|
||||
${CC} ${INCLUDE} -c ${CFLAGS} $< -o $@ ${LIBRARIES}
|
||||
@echo
|
||||
|
||||
${BIN}/%.o : ${SRC}/%.c
|
||||
@echo -e '\e[34;1m ==== compiling $< ====\e[0m'
|
||||
${DIR_GUARD}
|
||||
${CC} ${INCLUDE} -c ${CFLAGS} $< -o $@ ${LIBRARIES}
|
||||
@echo
|
||||
|
||||
${OBJ}/%.o : ${SRC}/%.s
|
||||
@echo -e '\e[35;1m ==== compiling $^ ====\e[0m'
|
||||
${DIR_GUARD}
|
||||
${AS} -o ${ASFLAGS} $< -o $@ ${LIBRARIES}
|
||||
@echo
|
||||
|
||||
${BIN}/%.o : ${SRC}/%.s
|
||||
@echo -e '\e[35;1m ==== compiling $^ ====\e[0m'
|
||||
${DIR_GUARD}
|
||||
${AS} -o ${ASFLAGS} $< -o $@ ${LIBRARIES}
|
||||
@echo
|
||||
|
||||
# --- remove generated files
|
||||
clean:
|
||||
-rm -rf ${BIN}/*
|
||||
|
||||
-include ${DEPEND_FILES}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
# stm32f1xx_HBL
|
||||
simplified HAL for stm32f1 microcontrollers, designed to be easily customized
|
||||
BIN
doc/cortex_m3.pdf
Normal file
BIN
doc/cortex_m3.pdf
Normal file
Binary file not shown.
331
doc/modules.drawio
Normal file
331
doc/modules.drawio
Normal file
@ -0,0 +1,331 @@
|
||||
<mxfile host="Electron" modified="2023-05-13T13:49:29.284Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.2.1 Chrome/106.0.5249.199 Electron/21.4.4 Safari/537.36" etag="hag9Pts7i5T_KBibxpc9" version="21.2.1" type="device">
|
||||
<diagram name="Page-1" id="nh8f32euryOmsLCMibi_">
|
||||
<mxGraphModel dx="1420" dy="1695" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-29" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Drivers</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;shadow=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="-690" width="1460" height="740" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-13" value="RCC" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;fillColor=#6d8764;strokeColor=#3A5431;labelBackgroundColor=none;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="150" y="-620" width="310" height="164" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-14" value="- regs : struct" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-13" vertex="1">
|
||||
<mxGeometry y="26" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-15" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" parent="v3HUPI7M600Mln0mNnSE-13" vertex="1">
|
||||
<mxGeometry y="52" width="310" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-8" value="+ rcc_configure (preset: enum)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-13" vertex="1">
|
||||
<mxGeometry y="60" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-6" value="+ rcc_enable (mask: ahb, mask: apb1, mask: apb2)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-13" vertex="1">
|
||||
<mxGeometry y="86" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-17" value="+ rcc_disable (mask: ahb, mask: apb1, mask: apb2)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-13" vertex="1">
|
||||
<mxGeometry y="112" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-20" value="+ rcc_reset (mask: apb1, mask: apb2)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-13" vertex="1">
|
||||
<mxGeometry y="138" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-30" value="TIM" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#e51400;strokeColor=#B20000;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="1370" y="-619" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-31" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-30" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-32" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-30" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-33" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-30" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-34" value="GPIO" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#6d8764;strokeColor=#3A5431;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="-620" width="360" height="204" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-35" value="- regs : struct" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-34" vertex="1">
|
||||
<mxGeometry y="26" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-36" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-34" vertex="1">
|
||||
<mxGeometry y="52" width="360" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-37" value="+ gpio_configure (enum: port, mask: pin, enum: mode, 
 enum: config): void


" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-34" vertex="1">
|
||||
<mxGeometry y="60" width="360" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ClqF0cL-BW29ZjaMUesU-8" value="+ gpio_reset (enum: port, mask: pin) " style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-34" vertex="1">
|
||||
<mxGeometry y="100" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ClqF0cL-BW29ZjaMUesU-5" value="+ gpio_read (enum: port, mask: pin): bool


" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-34" vertex="1">
|
||||
<mxGeometry y="126" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ClqF0cL-BW29ZjaMUesU-6" value="+ gpio_write (enum: port, mask: pin, bool: val) " style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-34" vertex="1">
|
||||
<mxGeometry y="152" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DX46o3M0sBaZfG6b8Zif-7" value="+ gpio_reset_peripheral () " style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="v3HUPI7M600Mln0mNnSE-34">
|
||||
<mxGeometry y="178" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-38" value="ADC" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#e51400;strokeColor=#B20000;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="1370" y="-399" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-39" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-38" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-40" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-38" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-41" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-38" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-42" value="BKP" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1000" y="-620" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-43" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-42" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-44" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-42" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-45" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-42" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-46" value="SPI" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1000" y="-400" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-47" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-46" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-48" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-46" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-49" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-46" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-50" value="I2C" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1190" y="-289" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-51" value="+ field: type" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-50" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-52" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-50" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-53" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-50" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-54" value="USART" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#fa6800;strokeColor=#C73500;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1370" y="-509" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-55" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-54" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-56" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-54" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-57" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-54" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-58" value="CAN ?" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1190" y="-179" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-59" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-58" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-60" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-58" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-61" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-58" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-62" value="WDG" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1000" y="-510" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-63" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-62" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-64" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-62" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-65" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-62" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-66" value="DMA" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#fa6800;strokeColor=#C73500;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1190" y="-399" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-67" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-66" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-68" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-66" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-69" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-66" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-70" value="PWR" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1190" y="-509" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-71" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-70" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-72" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-70" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-73" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-70" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-74" value="NVIC" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#6d8764;strokeColor=#3A5431;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="150" y="-424" width="310" height="242" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-75" value="- regs : struct" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="26" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-76" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="52" width="310" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-77" value="+ nvic_enable (int: interrupt)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="60" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="o2IW8Z8pTP8tj_kMgO3k-2" value="+ nvic_disable (int: interrupt)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="86" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="o2IW8Z8pTP8tj_kMgO3k-3" value="+ nvic_clear_pending (int: interrupt)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="112" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="o2IW8Z8pTP8tj_kMgO3k-4" value="+ nvic_set_priority (int: interrupt, int: priority)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="138" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="o2IW8Z8pTP8tj_kMgO3k-6" value="+ nvic_set_pending (int: interrupt)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="164" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="o2IW8Z8pTP8tj_kMgO3k-8" value="+ nvic_is_pending (int interrupt): bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="190" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="o2IW8Z8pTP8tj_kMgO3k-7" value="+ nvic_is_active (int interrupt): bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-74" vertex="1">
|
||||
<mxGeometry y="216" width="310" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-78" value="FLASH" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1370" y="-289" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-79" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-78" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-80" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-78" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-81" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-78" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-82" value="CRC" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="1000" y="-290" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-83" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-82" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-84" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-82" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-85" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-82" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-86" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Services</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;shadow=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="100" y="160" width="810" height="280" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-87" value="Task" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#e51400;strokeColor=#B20000;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="320" y="210" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-88" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-87" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-89" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-87" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-90" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-87" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-91" value="Debug" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="210" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-92" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-91" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-93" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-91" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-94" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-91" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-95" value="Eeprom ?" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="320" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-96" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-95" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-97" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-95" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-98" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-95" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-99" value="Display" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="680" y="210" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-100" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-99" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-101" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-99" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-102" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-99" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-103" value="Input" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#f0a30a;strokeColor=#BD7000;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="210" width="160" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-104" value="+ field: type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-103" vertex="1">
|
||||
<mxGeometry y="26" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-105" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="v3HUPI7M600Mln0mNnSE-103" vertex="1">
|
||||
<mxGeometry y="52" width="160" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="v3HUPI7M600Mln0mNnSE-106" value="+ method(type): type" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="v3HUPI7M600Mln0mNnSE-103" vertex="1">
|
||||
<mxGeometry y="60" width="160" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-1" value="EXTI" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#e3c800;strokeColor=#B09500;fontColor=#000000;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="-385" width="360" height="190" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-2" value="- regs : struct" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="BL1kyMswEt5U9iN2dzKQ-1" vertex="1">
|
||||
<mxGeometry y="26" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-3" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="BL1kyMswEt5U9iN2dzKQ-1" vertex="1">
|
||||
<mxGeometry y="52" width="360" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-4" value="+ exti_configure (mask: line, enum: port, func: callback)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="BL1kyMswEt5U9iN2dzKQ-1" vertex="1">
|
||||
<mxGeometry y="60" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DX46o3M0sBaZfG6b8Zif-1" value="+ exti_reset (mask: line)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="BL1kyMswEt5U9iN2dzKQ-1">
|
||||
<mxGeometry y="86" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DX46o3M0sBaZfG6b8Zif-5" value="+ exti_configure_specific (mask: line, func: callback)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="BL1kyMswEt5U9iN2dzKQ-1">
|
||||
<mxGeometry y="112" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DX46o3M0sBaZfG6b8Zif-6" value="+ exti_reset_specific (mask: line)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="BL1kyMswEt5U9iN2dzKQ-1">
|
||||
<mxGeometry y="138" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="DX46o3M0sBaZfG6b8Zif-8" value="+ exti_reset_peripheral () " style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="BL1kyMswEt5U9iN2dzKQ-1">
|
||||
<mxGeometry y="164" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-10" value="AFIO" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;shadow=0;fillColor=#6d8764;strokeColor=#3A5431;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="500" y="-160" width="360" height="86" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-11" value="- regs : struct" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="BL1kyMswEt5U9iN2dzKQ-10" vertex="1">
|
||||
<mxGeometry y="26" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-12" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;shadow=0;" parent="BL1kyMswEt5U9iN2dzKQ-10" vertex="1">
|
||||
<mxGeometry y="52" width="360" height="8" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="BL1kyMswEt5U9iN2dzKQ-13" value="+ afio_map_exti (mask: line, enum: port)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" parent="BL1kyMswEt5U9iN2dzKQ-10" vertex="1">
|
||||
<mxGeometry y="60" width="360" height="26" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
63
drv/afio.c
Normal file
63
drv/afio.c
Normal file
@ -0,0 +1,63 @@
|
||||
/** @file afio.c
|
||||
* Module handling Alternate Functions for Inputs/Outputs
|
||||
*
|
||||
* The module provides functions to remap ios to diverse peripherals
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "afio.h"
|
||||
#include "afio_regs.h"
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct AFIO* regs = (struct AFIO*)AFIO_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void afio_map_exti(enum ExtiLine line_mask, enum GpioPort port)
|
||||
{
|
||||
//ensure afio peripheral is enabled
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_NONE, RCC_APB2_AFIO);
|
||||
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
regs->EXTICR1.word &= ~(0xF << (4 * i));
|
||||
regs->EXTICR1.word |= (port << (4 * i));
|
||||
}
|
||||
}
|
||||
|
||||
line_mask = line_mask >> 4;
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
regs->EXTICR2.word &= ~(0xF << (4 * i));
|
||||
regs->EXTICR2.word |= (port << (4 * i));
|
||||
}
|
||||
}
|
||||
|
||||
line_mask = line_mask >> 4;
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
regs->EXTICR3.word &= ~(0xF << (4 * i));
|
||||
regs->EXTICR3.word |= (port << (4 * i));
|
||||
}
|
||||
}
|
||||
|
||||
line_mask = line_mask >> 4;
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
regs->EXTICR4.word &= ~(0xF << (4 * i));
|
||||
regs->EXTICR4.word |= (port << (4 * i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
33
drv/afio.h
Normal file
33
drv/afio.h
Normal file
@ -0,0 +1,33 @@
|
||||
/** @file afio.h
|
||||
* Module handling Alternate Functions for Inputs/Outputs
|
||||
*
|
||||
* The module provides functions to remap ios to diverse peripherals
|
||||
*/
|
||||
|
||||
#ifndef _AFIO_H_
|
||||
#define _AFIO_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#include "exti.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Maps the exti lines to gpio ports. The ExtiLine enum can be used as a
|
||||
* mask to configure multiple lines at the same time. This function is used by
|
||||
* the exti module to configure its line and calling it directly should should
|
||||
* thus normaly not be needed. It could however still be usefull when wanting to
|
||||
* change the port linked to an exti without reconfiguring it entirely
|
||||
*/
|
||||
void afio_map_exti(enum ExtiLine line_mask, enum GpioPort port);
|
||||
|
||||
|
||||
#endif //_AFIO_H_
|
||||
|
||||
125
drv/afio_regs.h
Normal file
125
drv/afio_regs.h
Normal file
@ -0,0 +1,125 @@
|
||||
/** @file afio_regs.h
|
||||
* Module defining the AFIO registers.
|
||||
*
|
||||
* Mainly made to be used by the afio module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _AFIO_REGS_H_
|
||||
#define _AFIO_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define AFIO_BASE_ADDRESS 0x40010000
|
||||
|
||||
union EVCR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t PIN:4;
|
||||
uint32_t PORT:3;
|
||||
uint32_t EVOE:1;
|
||||
uint32_t reserved1:24;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union MAPR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t SPI1_REMAP:1;
|
||||
uint32_t I2C1_REMAP:1;
|
||||
uint32_t USART1_REMAP:1;
|
||||
uint32_t USART2_REMAP:1;
|
||||
uint32_t USART3_REMAP:2;
|
||||
uint32_t TIM1_REMAP:2;
|
||||
uint32_t TIM2_REMAP:2;
|
||||
uint32_t TIM3_REMAP:2;
|
||||
uint32_t TIM4_REMAP:1;
|
||||
uint32_t CAN_REMAP:2;
|
||||
uint32_t PD01_REMAP:1;
|
||||
uint32_t TIM5CH4_REMAP:1;
|
||||
uint32_t ADC1_ETRGINJ_REMAP:1;
|
||||
uint32_t ADC1_ETRGREG_REMAP:1;
|
||||
uint32_t ADC2_ETRGINJ_REMAP:1;
|
||||
uint32_t ADC2_ETRGREG_REMAP:1;
|
||||
uint32_t reserved1:3;
|
||||
uint32_t SWJ_CFG:3;
|
||||
uint32_t reserved2:5;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union EXTICR1 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t EXTI0:4;
|
||||
uint32_t EXTI1:4;
|
||||
uint32_t EXTI2:4;
|
||||
uint32_t EXTI3:4;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union EXTICR2 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t EXTI4:4;
|
||||
uint32_t EXTI5:4;
|
||||
uint32_t EXTI6:4;
|
||||
uint32_t EXTI7:4;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union EXTICR3 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t EXTI8:4;
|
||||
uint32_t EXTI9:4;
|
||||
uint32_t EXTI10:4;
|
||||
uint32_t EXTI11:4;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union EXTICR4 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t EXTI12:4;
|
||||
uint32_t EXTI13:4;
|
||||
uint32_t EXTI14:4;
|
||||
uint32_t EXTI15:4;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union MAPR2 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1:5;
|
||||
uint32_t TIM9_REMAP:1;
|
||||
uint32_t TIM10_REMAP:1;
|
||||
uint32_t TIM11_REMAP:1;
|
||||
uint32_t TIM13_REMAP:1;
|
||||
uint32_t TIM14_REMAP:1;
|
||||
uint32_t FSMC_NADV:1;
|
||||
uint32_t reserved2:21;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) AFIO {
|
||||
union EVCR EVCR;
|
||||
union MAPR MAPR;
|
||||
union EXTICR1 EXTICR1;
|
||||
union EXTICR2 EXTICR2;
|
||||
union EXTICR3 EXTICR3;
|
||||
union EXTICR4 EXTICR4;
|
||||
union MAPR2 MAPR2;
|
||||
};
|
||||
|
||||
#endif //_AFIO_REGS_H_
|
||||
|
||||
335
drv/dma.c
Normal file
335
drv/dma.c
Normal file
@ -0,0 +1,335 @@
|
||||
/** @file dma.h
|
||||
* Module handling Direct Memory Access controller
|
||||
*
|
||||
* The module provides functions to configure the dma channels and controller
|
||||
* transfers
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "dma.h"
|
||||
#include "dma_regs.h"
|
||||
|
||||
#include "nvic.h"
|
||||
#include "rcc.h"
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static void configure_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph);
|
||||
static void start_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size);
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct DMA* const dma1 = (struct DMA*)DMA1_BASE_ADDRESS;
|
||||
static volatile struct DMA* const dma2 = (struct DMA*)DMA2_BASE_ADDRESS;
|
||||
static DmaCallback dma1_callbacks[7];
|
||||
static volatile void* dma1_cb_params[7];
|
||||
static DmaCallback dma2_callbacks[5];
|
||||
static volatile void* dma2_cb_params[5];
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void dma_configure(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph,
|
||||
DmaCallback callback, volatile void* cb_param)
|
||||
{
|
||||
//reset peripheral first, to ensure proper configuration
|
||||
dma_reset(dma, channel);
|
||||
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
rcc_enable(RCC_AHB_DMA1, RCC_APB1_NONE, RCC_APB2_NONE);
|
||||
configure_dma(dma1, channel, config_mask, periph);
|
||||
if (callback) {
|
||||
dma1_callbacks[channel] = callback;
|
||||
dma1_cb_params[channel] = cb_param;
|
||||
nvic_enable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
}
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
rcc_enable(RCC_AHB_DMA2, RCC_APB1_NONE, RCC_APB2_NONE);
|
||||
configure_dma(dma2, channel, config_mask, periph);
|
||||
if (callback) {
|
||||
dma2_callbacks[channel] = callback;
|
||||
dma2_cb_params[channel] = cb_param;
|
||||
nvic_enable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_reset(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
volatile struct DMA* periph;
|
||||
|
||||
//first, disable IRQs
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
periph = dma1;
|
||||
dma1_callbacks[channel] = NULL;
|
||||
nvic_disable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
periph = dma2;
|
||||
dma2_callbacks[channel] = NULL;
|
||||
nvic_disable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
//then, set all registers to reset value
|
||||
volatile struct DMA_CHANNEL* regs = &periph->CHANNELS[channel];
|
||||
regs->CCR.word = 0;
|
||||
regs->CNDTR.word = 0;
|
||||
regs->CMAR = 0;
|
||||
regs->CPAR = 0;
|
||||
}
|
||||
|
||||
void dma_start(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
if (dma1_callbacks[channel]) {
|
||||
nvic_enable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
}
|
||||
start_dma(dma1, channel, mem, size);
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
if (dma2_callbacks[channel]) {
|
||||
nvic_enable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
}
|
||||
start_dma(dma2, channel, mem, size);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_stop(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
reg_reset(dma1->CHANNELS[channel].CCR, DMA_CCR_EN);
|
||||
if (dma1_callbacks[channel]) {
|
||||
nvic_disable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
}
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
reg_reset(dma2->CHANNELS[channel].CCR, DMA_CCR_EN);
|
||||
if (dma2_callbacks[channel]) {
|
||||
nvic_disable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enter_critical(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
nvic_disable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
nvic_disable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_exit_critical(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
nvic_enable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
nvic_enable(NVIC_IRQ_DMA2_CHANNEL1 + channel);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t dma_get_remaining(enum DmaPeriph dma, enum DmaChannel channel)
|
||||
{
|
||||
switch (dma) {
|
||||
case DMA_PERIPH_1:
|
||||
return dma1->CHANNELS[channel].CNDTR.NDT;
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
return dma2->CHANNELS[channel].CNDTR.NDT;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Applies the given configuration mask to the given DMA channel
|
||||
*/
|
||||
static void configure_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph)
|
||||
{
|
||||
volatile struct DMA_CHANNEL* regs = &dma->CHANNELS[channel];
|
||||
|
||||
//registers should already be at reset value, apply new config
|
||||
regs->CCR.word = config_mask;
|
||||
regs->CPAR = (uint32_t)periph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the given DMA channel using the given parameters
|
||||
*/
|
||||
static void start_dma(volatile struct DMA* dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size)
|
||||
{
|
||||
volatile struct DMA_CHANNEL* regs = &dma->CHANNELS[channel];
|
||||
|
||||
//registers should already be configured, apply transfer config
|
||||
reg_write(regs->CNDTR, DMA_CNDTR_NDT, size);
|
||||
regs->CMAR = (uint32_t)mem;
|
||||
|
||||
//only start transfer when everything is configured
|
||||
reg_set(regs->CCR, DMA_CCR_EN);
|
||||
}
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_dma1_channel1(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL1);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 1) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF1);
|
||||
|
||||
dma1_callbacks[0](src, dma1_cb_params[0]);
|
||||
}
|
||||
|
||||
void hdr_dma1_channel2(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL2);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 5) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF2);
|
||||
|
||||
dma1_callbacks[1](src, dma1_cb_params[1]);
|
||||
}
|
||||
|
||||
void hdr_dma1_channel3(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL3);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 9) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF3);
|
||||
|
||||
dma1_callbacks[2](src, dma1_cb_params[2]);
|
||||
}
|
||||
|
||||
void hdr_dma1_channel4(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL4);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 13) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF4);
|
||||
|
||||
dma1_callbacks[3](src, dma1_cb_params[3]);
|
||||
}
|
||||
|
||||
void hdr_dma1_channel5(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL5);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 17) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF5);
|
||||
|
||||
dma1_callbacks[4](src, dma1_cb_params[4]);
|
||||
}
|
||||
|
||||
void hdr_dma1_channel6(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL6);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 21) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF6);
|
||||
|
||||
dma1_callbacks[5](src, dma1_cb_params[5]);
|
||||
}
|
||||
|
||||
void hdr_dma1_channel7(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL7);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 25) & 0x7;
|
||||
reg_set(dma1->IFCR, DMA_IFCR_CGIF7);
|
||||
|
||||
dma1_callbacks[6](src, dma1_cb_params[6]);
|
||||
}
|
||||
|
||||
void hdr_dma2_channel1(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL1);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 1) & 0x7;
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF1);
|
||||
|
||||
dma2_callbacks[0](src, dma2_cb_params[0]);
|
||||
}
|
||||
|
||||
void hdr_dma2_channel2(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL2);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 5) & 0x7;
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF2);
|
||||
|
||||
dma2_callbacks[1](src, dma2_cb_params[1]);
|
||||
}
|
||||
|
||||
void hdr_dma2_channel3(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL3);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 9) & 0x7;
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF3);
|
||||
|
||||
dma2_callbacks[2](src, dma2_cb_params[2]);
|
||||
}
|
||||
|
||||
void hdr_dma2_channel4_5(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA2_CHANNEL4_5);
|
||||
|
||||
enum DmaIRQSource src = (dma2->IFCR.word >> 13) & 0x7;
|
||||
if (src != 0) {
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF4);
|
||||
dma1_callbacks[3](src, dma2_cb_params[3]);
|
||||
}
|
||||
|
||||
src = (dma2->IFCR.word >> 17) & 0x7;
|
||||
if (src != 0) {
|
||||
reg_set(dma2->IFCR, DMA_IFCR_CGIF5);
|
||||
dma1_callbacks[4](src, dma2_cb_params[4]);
|
||||
}
|
||||
}
|
||||
|
||||
180
drv/dma.h
Normal file
180
drv/dma.h
Normal file
@ -0,0 +1,180 @@
|
||||
/** @file dma.h
|
||||
* Module handling Direct Memory Access controller
|
||||
*
|
||||
* The module provides functions to configure the dma channels and controller
|
||||
* transfers
|
||||
*/
|
||||
|
||||
#ifndef _DMA_H_
|
||||
#define _DMA_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available DMA peripherals. Note that some of these peripherals may not be
|
||||
* available on all chips
|
||||
*/
|
||||
enum DmaPeriph {
|
||||
DMA_PERIPH_1,
|
||||
DMA_PERIPH_2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Available DMA channels. Note that some of these channels may not be
|
||||
* available on all chips and all DMA peripheral
|
||||
*/
|
||||
enum DmaChannel {
|
||||
DMA_CHANNEL_1 = 0,
|
||||
DMA_CHANNEL_2,
|
||||
DMA_CHANNEL_3,
|
||||
DMA_CHANNEL_4,
|
||||
DMA_CHANNEL_5,
|
||||
DMA_CHANNEL_6, //not available for DMA 2
|
||||
DMA_CHANNEL_7, //not available for DMA 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration options for memory-to-peripheral transfers
|
||||
*/
|
||||
enum DmaConfig {
|
||||
DMA_CONFIG_IRQ_COMPLETE = (0x1 << 1),
|
||||
DMA_CONFIG_IRQ_HALF = (0x1 << 2),
|
||||
DMA_CONFIG_IRQ_ERROR = (0x1 << 3),
|
||||
DMA_CONFIG_FROM_MEM = (0x1 << 4),
|
||||
DMA_CONFIG_FROM_PERIPH = (0x0 << 4),
|
||||
DMA_CONFIG_CIRCULAR = (0x1 << 5),
|
||||
DMA_CONFIG_INC_PERIPH = (0x1 << 6),
|
||||
DMA_CONFIG_INC_MEM = (0x1 << 7),
|
||||
DMA_CONFIG_PSIZE_8BITS = (0x0 << 8),
|
||||
DMA_CONFIG_PSIZE_16BITS = (0x1 << 8),
|
||||
DMA_CONFIG_PSIZE_32BITS = (0x2 << 8),
|
||||
DMA_CONFIG_MSIZE_8BITS = (0x0 << 10),
|
||||
DMA_CONFIG_MSIZE_16BITS = (0x1 << 10),
|
||||
DMA_CONFIG_MSIZE_32BITS = (0x2 << 10),
|
||||
DMA_CONFIG_PRIO_LOW = (0x0 << 12),
|
||||
DMA_CONFIG_PRIO_MEDIUM = (0x1 << 12),
|
||||
DMA_CONFIG_PRIO_HIGH = (0x2 << 12),
|
||||
DMA_CONFIG_PRIO_VHIGH = (0x3 << 12),
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration options for memory-to-memory transfers
|
||||
*/
|
||||
enum DmaConfigM2M {
|
||||
DMA_CONFIG_M2M_IRQ_COMPLETE = (0x1 << 1),
|
||||
DMA_CONFIG_M2M_IRQ_HALF = (0x1 << 2),
|
||||
DMA_CONFIG_M2M_IRQ_ERROR = (0x1 << 3),
|
||||
DMA_CONFIG_M2M_INC_SRC = (0x1 << 6),
|
||||
DMA_CONFIG_M2M_INC_DEST = (0x1 << 7),
|
||||
DMA_CONFIG_M2M_SSIZE_8BITS = (0x0 << 8),
|
||||
DMA_CONFIG_M2M_SSIZE_16BITS = (0x1 << 8),
|
||||
DMA_CONFIG_M2M_SSIZE_32BITS = (0x2 << 8),
|
||||
DMA_CONFIG_M2M_DSIZE_8BITS = (0x0 << 10),
|
||||
DMA_CONFIG_M2M_DSIZE_16BITS = (0x1 << 10),
|
||||
DMA_CONFIG_M2M_DSIZE_32BITS = (0x2 << 10),
|
||||
DMA_CONFIG_M2M_PRIO_LOW = (0x0 << 12),
|
||||
DMA_CONFIG_M2M_PRIO_MEDIUM = (0x1 << 12),
|
||||
DMA_CONFIG_M2M_PRIO_HIGH = (0x2 << 12),
|
||||
DMA_CONFIG_M2M_PRIO_VHIGH = (0x3 << 12),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available sources for a DMA IRQ. These sources can be enabled independently
|
||||
* in the DMA configuration.
|
||||
*/
|
||||
enum DmaIRQSource {
|
||||
DMA_IRQ_SOURCE_COMPLETE = (0x1 << 1),
|
||||
DMA_IRQ_SOURCE_HALF = (0x1 << 2),
|
||||
DMA_IQR_SOURCE_ERROR = (0x2 << 3),
|
||||
};
|
||||
|
||||
/**
|
||||
* Prototype of the IRQ callbacks that the applicative code can provide
|
||||
*/
|
||||
typedef void (*DmaCallback)(enum DmaIRQSource, volatile void* param);
|
||||
|
||||
/**
|
||||
* Generic struct used to share DAM configs between peripheral drivers and
|
||||
* services providing DMA interfaces
|
||||
*/
|
||||
struct DmaParam {
|
||||
void* periph;
|
||||
enum DmaConfig config; //DMA config, must correspond to peripheral
|
||||
enum DmaPeriph dma; //DMA peripheral, must correspond to peripheral
|
||||
enum DmaChannel channel; //DMA channel, must correspond to peripheral
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the given DMA channel with the provided configuration, to perform
|
||||
* a transfer to or from the given peripheral register. The specified callback,
|
||||
* if any, will be called on the enabled IRQ sources, with the specified
|
||||
* parameter, if any.
|
||||
*
|
||||
* This function doesn't initiate transfers, use dma_start() for that
|
||||
*/
|
||||
void dma_configure(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
enum DmaConfig config_mask, volatile void* periph,
|
||||
DmaCallback callback, volatile void* cb_param);
|
||||
|
||||
/**
|
||||
* Unimplemented
|
||||
*/
|
||||
void dma_configure_mem2mem(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
enum DmaConfigM2M config_mask, const void* src, void* dest,
|
||||
uint16_t size, DmaCallback callback, void* cb_param);
|
||||
|
||||
/**
|
||||
* Resets the given DMA channel, restoring the default configuration and
|
||||
* disabling it
|
||||
*/
|
||||
void dma_reset(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
/**
|
||||
* Initiate a transfer on the given DMA channel, to or from the given memory
|
||||
* address, and of the specified size.
|
||||
*
|
||||
* Should only be used after the channel has been configured through
|
||||
* dma_configure()
|
||||
* All transfers started must be eventually stopped, or the channel reset, for
|
||||
* proper IRQ behavior.
|
||||
*/
|
||||
void dma_start(enum DmaPeriph dma, enum DmaChannel channel,
|
||||
volatile void* mem, uint16_t size);
|
||||
|
||||
/**
|
||||
* Stops a transfer on the given DMA channel. If the transfer has already
|
||||
* ended, properly shutdown the channel. Configuration is not lost after calling
|
||||
* this function and dma_start() may be called again
|
||||
*/
|
||||
void dma_stop(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
/**
|
||||
* Enters a DMA critical section, disabling the given channel's IRQs until
|
||||
* dma_exit_critical() is called
|
||||
*/
|
||||
void dma_enter_critical(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
/**
|
||||
* Exists a DMA critical section previously entered through
|
||||
* dma_enter_critical(). Reenables the given channel's IRQs
|
||||
*/
|
||||
void dma_exit_critical(enum DmaPeriph dma, enum DmaChannel channel);
|
||||
|
||||
/**
|
||||
* Returns the remaining number of bytes to be transmitted while a transfer is
|
||||
* running. When no transfer is running, returns the number of bytes to transfer
|
||||
* next
|
||||
*/
|
||||
uint16_t dma_get_remaining(enum DmaPeriph dma, enum DmaChannel channe);
|
||||
|
||||
|
||||
#endif //_DMA_H_
|
||||
|
||||
216
drv/dma_regs.h
Normal file
216
drv/dma_regs.h
Normal file
@ -0,0 +1,216 @@
|
||||
/** @file dma_regs.h
|
||||
* Module defining the DMA registers.
|
||||
*
|
||||
* Mainly made to be used by the dma module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _DMA_REGS_H_
|
||||
#define _DMA_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define DMA1_BASE_ADDRESS 0x40020000
|
||||
#define DMA2_BASE_ADDRESS 0x40020400
|
||||
|
||||
union DMA_ISR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t GIF1:1;
|
||||
uint32_t TCIF1:1;
|
||||
uint32_t HTIF1:1;
|
||||
uint32_t TEIF1:1;
|
||||
uint32_t GIF2:1;
|
||||
uint32_t TCIF2:1;
|
||||
uint32_t HTIF2:1;
|
||||
uint32_t TEIF2:1;
|
||||
uint32_t GIF3:1;
|
||||
uint32_t TCIF3:1;
|
||||
uint32_t HTIF3:1;
|
||||
uint32_t TEIF3:1;
|
||||
uint32_t GIF4:1;
|
||||
uint32_t TCIF4:1;
|
||||
uint32_t HTIF4:1;
|
||||
uint32_t TEIF4:1;
|
||||
uint32_t GIF5:1;
|
||||
uint32_t TCIF5:1;
|
||||
uint32_t HTIF5:1;
|
||||
uint32_t TEIF5:1;
|
||||
uint32_t GIF6:1;
|
||||
uint32_t TCIF6:1;
|
||||
uint32_t HTIF6:1;
|
||||
uint32_t TEIF6:1;
|
||||
uint32_t GIF7:1;
|
||||
uint32_t TCIF7:1;
|
||||
uint32_t HTIF7:1;
|
||||
uint32_t TEIF7:1;
|
||||
uint32_t reserved1:4;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_ISR_GIF1 reg_def( 0, 1)
|
||||
#define DMA_ISR_TCIF1 reg_def( 1, 1)
|
||||
#define DMA_ISR_HTIF1 reg_def( 2, 1)
|
||||
#define DMA_ISR_TEIF1 reg_def( 3, 1)
|
||||
#define DMA_ISR_GIF2 reg_def( 4, 1)
|
||||
#define DMA_ISR_TCIF2 reg_def( 5, 1)
|
||||
#define DMA_ISR_HTIF2 reg_def( 6, 1)
|
||||
#define DMA_ISR_TEIF2 reg_def( 7, 1)
|
||||
#define DMA_ISR_GIF3 reg_def( 8, 1)
|
||||
#define DMA_ISR_TCIF3 reg_def( 9, 1)
|
||||
#define DMA_ISR_HTIF3 reg_def(10, 1)
|
||||
#define DMA_ISR_TEIF3 reg_def(11, 1)
|
||||
#define DMA_ISR_GIF4 reg_def(12, 1)
|
||||
#define DMA_ISR_TCIF4 reg_def(13, 1)
|
||||
#define DMA_ISR_HTIF4 reg_def(14, 1)
|
||||
#define DMA_ISR_TEIF4 reg_def(15, 1)
|
||||
#define DMA_ISR_GIF5 reg_def(16, 1)
|
||||
#define DMA_ISR_TCIF5 reg_def(17, 1)
|
||||
#define DMA_ISR_HTIF5 reg_def(18, 1)
|
||||
#define DMA_ISR_TEIF5 reg_def(19, 1)
|
||||
#define DMA_ISR_GIF6 reg_def(20, 1)
|
||||
#define DMA_ISR_TCIF6 reg_def(21, 1)
|
||||
#define DMA_ISR_HTIF6 reg_def(22, 1)
|
||||
#define DMA_ISR_TEIF6 reg_def(23, 1)
|
||||
#define DMA_ISR_GIF7 reg_def(24, 1)
|
||||
#define DMA_ISR_TCIF7 reg_def(25, 1)
|
||||
#define DMA_ISR_HTIF7 reg_def(26, 1)
|
||||
#define DMA_ISR_TEIF7 reg_def(27, 1)
|
||||
#define DMA_ISR_reserved1 reg_def(28, 4)
|
||||
|
||||
union DMA_IFCR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t CGIF1:1;
|
||||
uint32_t CTCIF1:1;
|
||||
uint32_t CHTIF1:1;
|
||||
uint32_t CTEIF1:1;
|
||||
uint32_t CGIF2:1;
|
||||
uint32_t CTCIF2:1;
|
||||
uint32_t CHTIF2:1;
|
||||
uint32_t CTEIF2:1;
|
||||
uint32_t CGIF3:1;
|
||||
uint32_t CTCIF3:1;
|
||||
uint32_t CHTIF3:1;
|
||||
uint32_t CTEIF3:1;
|
||||
uint32_t CGIF4:1;
|
||||
uint32_t CTCIF4:1;
|
||||
uint32_t CHTIF4:1;
|
||||
uint32_t CTEIF4:1;
|
||||
uint32_t CGIF5:1;
|
||||
uint32_t CTCIF5:1;
|
||||
uint32_t CHTIF5:1;
|
||||
uint32_t CTEIF5:1;
|
||||
uint32_t CGIF6:1;
|
||||
uint32_t CTCIF6:1;
|
||||
uint32_t CHTIF6:1;
|
||||
uint32_t CTEIF6:1;
|
||||
uint32_t CGIF7:1;
|
||||
uint32_t CTCIF7:1;
|
||||
uint32_t CHTIF7:1;
|
||||
uint32_t CTEIF7:1;
|
||||
uint32_t reserved1:4;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_IFCR_CGIF1 reg_def( 0, 1)
|
||||
#define DMA_IFCR_CTCIF1 reg_def( 1, 1)
|
||||
#define DMA_IFCR_CHTIF1 reg_def( 2, 1)
|
||||
#define DMA_IFCR_CTEIF1 reg_def( 3, 1)
|
||||
#define DMA_IFCR_CGIF2 reg_def( 4, 1)
|
||||
#define DMA_IFCR_CTCIF2 reg_def( 5, 1)
|
||||
#define DMA_IFCR_CHTIF2 reg_def( 6, 1)
|
||||
#define DMA_IFCR_CTEIF2 reg_def( 7, 1)
|
||||
#define DMA_IFCR_CGIF3 reg_def( 8, 1)
|
||||
#define DMA_IFCR_CTCIF3 reg_def( 9, 1)
|
||||
#define DMA_IFCR_CHTIF3 reg_def(10, 1)
|
||||
#define DMA_IFCR_CTEIF3 reg_def(11, 1)
|
||||
#define DMA_IFCR_CGIF4 reg_def(12, 1)
|
||||
#define DMA_IFCR_CTCIF4 reg_def(13, 1)
|
||||
#define DMA_IFCR_CHTIF4 reg_def(14, 1)
|
||||
#define DMA_IFCR_CTEIF4 reg_def(15, 1)
|
||||
#define DMA_IFCR_CGIF5 reg_def(16, 1)
|
||||
#define DMA_IFCR_CTCIF5 reg_def(17, 1)
|
||||
#define DMA_IFCR_CHTIF5 reg_def(18, 1)
|
||||
#define DMA_IFCR_CTEIF5 reg_def(19, 1)
|
||||
#define DMA_IFCR_CGIF6 reg_def(20, 1)
|
||||
#define DMA_IFCR_CTCIF6 reg_def(21, 1)
|
||||
#define DMA_IFCR_CHTIF6 reg_def(22, 1)
|
||||
#define DMA_IFCR_CTEIF6 reg_def(23, 1)
|
||||
#define DMA_IFCR_CGIF7 reg_def(24, 1)
|
||||
#define DMA_IFCR_CTCIF7 reg_def(25, 1)
|
||||
#define DMA_IFCR_CHTIF7 reg_def(26, 1)
|
||||
#define DMA_IFCR_CTEIF7 reg_def(27, 1)
|
||||
#define DMA_IFCR_reserved1 reg_def(28, 4)
|
||||
|
||||
union DMA_CCR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t EN:1;
|
||||
uint32_t TCIE:1;
|
||||
uint32_t HTIE:1;
|
||||
uint32_t TEIE:1;
|
||||
uint32_t DIR:1;
|
||||
uint32_t CIRC:1;
|
||||
uint32_t PINC:1;
|
||||
uint32_t MINC:1;
|
||||
uint32_t PSIZE:2;
|
||||
uint32_t MSIZE:2;
|
||||
uint32_t PL:2;
|
||||
uint32_t MEM2MEM:1;
|
||||
uint32_t reserved1:17;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_CCR_EN reg_def( 0, 1)
|
||||
#define DMA_CCR_TCIE reg_def( 1, 1)
|
||||
#define DMA_CCR_HTIE reg_def( 2, 1)
|
||||
#define DMA_CCR_TEIE reg_def( 3, 1)
|
||||
#define DMA_CCR_DIR reg_def( 4, 1)
|
||||
#define DMA_CCR_CIRC reg_def( 5, 1)
|
||||
#define DMA_CCR_PINC reg_def( 6, 1)
|
||||
#define DMA_CCR_MINC reg_def( 7, 1)
|
||||
#define DMA_CCR_PSIZE reg_def( 8, 2)
|
||||
#define DMA_CCR_MSIZE reg_def(10, 2)
|
||||
#define DMA_CCR_PL reg_def(12, 2)
|
||||
#define DMA_CCR_MEM2MEM reg_def(14, 1)
|
||||
#define DMA_CCR_reserved1 reg_def(15, 17)
|
||||
|
||||
union DMA_CNDTR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t NDT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define DMA_CNDTR_NDT reg_def( 0, 16)
|
||||
#define DMA_CNDTR_reserved1 reg_def(16, 16)
|
||||
|
||||
struct __attribute__((packed)) DMA_CHANNEL {
|
||||
union DMA_CCR CCR;
|
||||
union DMA_CNDTR CNDTR;
|
||||
uint32_t CPAR;
|
||||
uint32_t CMAR;
|
||||
uint32_t reserved1;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) DMA {
|
||||
union DMA_ISR ISR;
|
||||
union DMA_IFCR IFCR;
|
||||
struct DMA_CHANNEL CHANNELS[7];
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_DMA_REGS_H_
|
||||
|
||||
270
drv/exti.c
Normal file
270
drv/exti.c
Normal file
@ -0,0 +1,270 @@
|
||||
/** @file exti.c
|
||||
* Module handling EXTernal Interrupt lines
|
||||
*
|
||||
* The module provides functions to configure the exti lines to generate events
|
||||
* or interrupts
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "exti.h"
|
||||
#include "exti_regs.h"
|
||||
|
||||
#include "nvic.h"
|
||||
#include "afio.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct EXTI* regs = (struct EXTI*)EXTI_BASE_ADDRESS;
|
||||
static ExtiCallback callbacks[19];
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback)
|
||||
{
|
||||
exti_reset(line_mask);
|
||||
|
||||
afio_map_exti(line_mask, port);
|
||||
|
||||
//configure edge detections
|
||||
if (config_mask & EXTI_CONFIG_RISING_EDGE) {
|
||||
regs->RTSR.word |= line_mask;
|
||||
} else {
|
||||
regs->RTSR.word &= ~line_mask;
|
||||
}
|
||||
|
||||
if (config_mask & EXTI_CONFIG_FALLING_EDGE) {
|
||||
regs->FTSR.word |= line_mask;
|
||||
} else {
|
||||
regs->FTSR.word &= ~line_mask;
|
||||
}
|
||||
|
||||
//reconfigure events/irqs
|
||||
regs->EMR.word |= line_mask;
|
||||
if (callback) {
|
||||
//register callbacks for each line selected
|
||||
for (uint8_t i = 0; i < 16; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
callbacks[i] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
//enable interrupts lines in nvic
|
||||
for (uint8_t i = 0; i < 5; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
nvic_enable(NVIC_IRQ_EXTI0 + i);
|
||||
}
|
||||
}
|
||||
if (line_mask & 0x3e0) {
|
||||
nvic_enable(NVIC_IRQ_EXTI9_5);
|
||||
}
|
||||
if (line_mask & 0x7c00) {
|
||||
nvic_enable(NVIC_IRQ_EXTI15_10);
|
||||
}
|
||||
|
||||
//enable irqs in last to avoid triggers during config
|
||||
regs->IMR.word |= line_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void exti_reset(enum ExtiLine line_mask)
|
||||
{
|
||||
//disable events/irqs
|
||||
regs->IMR.word &= ~line_mask;
|
||||
regs->EMR.word &= ~line_mask;
|
||||
|
||||
//clear any pending bits
|
||||
regs->PR.word |= line_mask;
|
||||
|
||||
//disable interrupts lines in nvic
|
||||
for (uint8_t i = 0; i < 5; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
nvic_disable(NVIC_IRQ_EXTI0 + i);
|
||||
}
|
||||
}
|
||||
if (line_mask & 0x3e0) {
|
||||
nvic_disable(NVIC_IRQ_EXTI9_5);
|
||||
}
|
||||
if (line_mask & 0x7c00) {
|
||||
nvic_disable(NVIC_IRQ_EXTI15_10);
|
||||
}
|
||||
|
||||
afio_map_exti(0xFFFF, 0x0);
|
||||
}
|
||||
|
||||
void exti_configure_specific(enum ExtiLineSpecific line_mask,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback)
|
||||
{
|
||||
//reset is identical to normal lines
|
||||
exti_reset_specific(line_mask);
|
||||
|
||||
//configure edge detections
|
||||
if (config_mask & EXTI_CONFIG_RISING_EDGE) {
|
||||
regs->RTSR.word |= line_mask;
|
||||
} else {
|
||||
regs->RTSR.word &= ~line_mask;
|
||||
}
|
||||
|
||||
if (config_mask & EXTI_CONFIG_FALLING_EDGE) {
|
||||
regs->FTSR.word |= line_mask;
|
||||
} else {
|
||||
regs->FTSR.word &= ~line_mask;
|
||||
}
|
||||
|
||||
//reconfigure events/irqs
|
||||
regs->EMR.word |= line_mask;
|
||||
if (callback) {
|
||||
//register callbacks for each line selected
|
||||
for (uint8_t i = 0; i < 16; ++i) {
|
||||
if (line_mask & (0x1 << i)) {
|
||||
callbacks[i] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
//enable interrupts lines in nvic
|
||||
if (line_mask & EXTI_LINE_PVD) {
|
||||
nvic_enable(NVIC_IRQ_PVD);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_RTC) {
|
||||
nvic_enable(NVIC_IRQ_RTC_ALARM);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_USB) {
|
||||
nvic_enable(NVIC_IRQ_USB_WAKEUP);
|
||||
}
|
||||
|
||||
//enable irqs in last to avoid triggers during config
|
||||
regs->IMR.word |= line_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void exti_reset_specific(enum ExtiLineSpecific line_mask)
|
||||
{
|
||||
//disable events/irqs
|
||||
regs->IMR.word &= ~line_mask;
|
||||
regs->EMR.word &= ~line_mask;
|
||||
|
||||
//clear any pending bits
|
||||
regs->PR.word |= line_mask;
|
||||
|
||||
//disable interrupts lines in nvic
|
||||
if (line_mask & EXTI_LINE_PVD) {
|
||||
nvic_disable(NVIC_IRQ_PVD);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_RTC) {
|
||||
nvic_disable(NVIC_IRQ_RTC_ALARM);
|
||||
}
|
||||
if (line_mask & EXTI_LINE_USB) {
|
||||
nvic_disable(NVIC_IRQ_USB_WAKEUP);
|
||||
}
|
||||
}
|
||||
|
||||
void exti_reset_peripheral(void)
|
||||
{
|
||||
//reset peripheral config
|
||||
regs->IMR.word = 0;
|
||||
regs->EMR.word = 0;
|
||||
regs->RTSR.word = 0;
|
||||
regs->FTSR.word = 0;
|
||||
regs->SWIER.word = 0;
|
||||
regs->PR.word = 0;
|
||||
|
||||
//disable interrupts in nvic
|
||||
for (uint8_t i = 0; i < 5; ++i) {
|
||||
nvic_enable(NVIC_IRQ_EXTI0 + i);
|
||||
}
|
||||
nvic_enable(NVIC_IRQ_EXTI9_5);
|
||||
nvic_enable(NVIC_IRQ_EXTI15_10);
|
||||
nvic_disable(NVIC_IRQ_PVD);
|
||||
nvic_disable(NVIC_IRQ_RTC_ALARM);
|
||||
nvic_disable(NVIC_IRQ_USB_WAKEUP);
|
||||
|
||||
afio_map_exti(0xFFFF, 0x0);
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_exti0(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI0);
|
||||
reg_set(regs->PR, EXTI_PR_PR0);
|
||||
callbacks[0]();
|
||||
}
|
||||
|
||||
void hdr_exti1(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI1);
|
||||
reg_set(regs->PR, EXTI_PR_PR1);
|
||||
callbacks[1]();
|
||||
}
|
||||
|
||||
void hdr_exti2(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI2);
|
||||
reg_set(regs->PR, EXTI_PR_PR2);
|
||||
callbacks[2]();
|
||||
}
|
||||
|
||||
void hdr_exti3(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI3);
|
||||
reg_set(regs->PR, EXTI_PR_PR3);
|
||||
callbacks[3]();
|
||||
}
|
||||
|
||||
void hdr_exti4(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI4);
|
||||
reg_set(regs->PR, EXTI_PR_PR4);
|
||||
callbacks[4]();
|
||||
}
|
||||
|
||||
void hdr_exti9_5(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI9_5);
|
||||
for (uint8_t i = 5; i < 10; ++i) {
|
||||
if (regs->PR.word & (0x1 << i)) {
|
||||
regs->PR.word |= 0x1 << i;
|
||||
callbacks[i]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hdr_exti15_10(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI15_10);
|
||||
for (uint8_t i = 10; i < 16; ++i) {
|
||||
if (regs->PR.word & (0x1 << i)) {
|
||||
regs->PR.word |= 0x1 << i;
|
||||
callbacks[i]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hdr_pvd(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_PVD);
|
||||
reg_set(regs->PR, EXTI_PR_PR16);
|
||||
callbacks[16]();
|
||||
}
|
||||
|
||||
void hdr_rtc_alarm(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_RTC_ALARM);
|
||||
reg_set(regs->PR, EXTI_PR_PR17);
|
||||
callbacks[17]();
|
||||
}
|
||||
|
||||
void hdr_usb_wakeup(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_USB_WAKEUP);
|
||||
reg_set(regs->PR, EXTI_PR_PR18);
|
||||
callbacks[18]();
|
||||
}
|
||||
|
||||
111
drv/exti.h
Normal file
111
drv/exti.h
Normal file
@ -0,0 +1,111 @@
|
||||
/** @file exti.h
|
||||
* Module handling EXTernal Interrupt lines
|
||||
*
|
||||
* The module provides functions to configure the exti lines to generate events
|
||||
* or interrupts
|
||||
*/
|
||||
|
||||
#ifndef _EXTI_H_
|
||||
#define _EXTI_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available exti lines. These lines correspond to gpios
|
||||
*/
|
||||
enum ExtiLine {
|
||||
EXTI_LINE_0 = (0x1 << 0),
|
||||
EXTI_LINE_1 = (0x1 << 1),
|
||||
EXTI_LINE_2 = (0x1 << 2),
|
||||
EXTI_LINE_3 = (0x1 << 3),
|
||||
EXTI_LINE_4 = (0x1 << 4),
|
||||
EXTI_LINE_5 = (0x1 << 5),
|
||||
EXTI_LINE_6 = (0x1 << 6),
|
||||
EXTI_LINE_7 = (0x1 << 7),
|
||||
EXTI_LINE_8 = (0x1 << 8),
|
||||
EXTI_LINE_9 = (0x1 << 9),
|
||||
EXTI_LINE_10 = (0x1 << 10),
|
||||
EXTI_LINE_11 = (0x1 << 11),
|
||||
EXTI_LINE_12 = (0x1 << 12),
|
||||
EXTI_LINE_13 = (0x1 << 13),
|
||||
EXTI_LINE_14 = (0x1 << 14),
|
||||
EXTI_LINE_15 = (0x1 << 15),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available exti lines. These lines correspond to specific peripherals
|
||||
*/
|
||||
enum ExtiLineSpecific {
|
||||
EXTI_LINE_PVD = (0x1 << 16),
|
||||
EXTI_LINE_RTC = (0x1 << 17),
|
||||
EXTI_LINE_USB = (0x1 << 18),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available configurations for exti lines. These configurations apply to both
|
||||
* regular and specific lines and can be used together on a single line
|
||||
*/
|
||||
enum ExtiConfig {
|
||||
EXTI_CONFIG_RISING_EDGE = (0x1 << 0),
|
||||
EXTI_CONFIG_FALLING_EDGE = (0x1 << 1),
|
||||
};
|
||||
|
||||
typedef void (*ExtiCallback)(void);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configure lines on a single GPIO port. The ExtiLine enum can be used as a
|
||||
* mask to configure multiple lines at the same time. Every line can only be
|
||||
* configured for a single port, reconfiguring it will override the previous
|
||||
* configuration. Each line is linked to the pins of the same id (ex : pin 1 for
|
||||
* exti 1). When possible, it is recommanded to use the lowest id possible for
|
||||
* better performance. The ExtiConfig enum can be used as mask. If no callback
|
||||
* is specified, the interrupt won't be enabled, but an event will still be sent
|
||||
* to wake the cpu up.
|
||||
*
|
||||
* Note: wich port is linked to a line can be changed atfer the fact using
|
||||
* afio_map_exti()
|
||||
*/
|
||||
void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback);
|
||||
|
||||
/**
|
||||
* Resets lines. The ExtiLine enum can be used as a mask to configure multiple
|
||||
* lines at the same time
|
||||
*/
|
||||
void exti_reset(enum ExtiLine line_mask);
|
||||
|
||||
/**
|
||||
* Configure lines for specific, non-gpio peripherals. The ExtiLineSpecific enum
|
||||
* can be used as a mask to configure multiple lines at the same time. The
|
||||
* ExtiConfig enum can be used as mask. If no callback is specified, the
|
||||
* interrupt won't be enabled, but an event will still be sent to wake the cpu
|
||||
* up
|
||||
*/
|
||||
void exti_configure_specific(enum ExtiLineSpecific line_mask,
|
||||
enum ExtiConfig config_mask, ExtiCallback callback);
|
||||
|
||||
/**
|
||||
* Resets lines for specific, non-gpio peripherals. The ExtiLineSpecific enum
|
||||
* can be used as a mask to configure multiple lines at the same time.
|
||||
*/
|
||||
void exti_reset_specific(enum ExtiLineSpecific line_mask);
|
||||
|
||||
/**
|
||||
* Resets all lines. The exti peripheral is returned to its reset configuration
|
||||
*/
|
||||
void exti_reset_peripheral(void);
|
||||
|
||||
|
||||
#endif //_EXTI_H_
|
||||
|
||||
318
drv/exti_regs.h
Normal file
318
drv/exti_regs.h
Normal file
@ -0,0 +1,318 @@
|
||||
/** @file exti_regs.h
|
||||
* Module defining the EXTI registers
|
||||
*
|
||||
* Mainly made to be used by the exti module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _EXTI_REGS_H_
|
||||
#define _EXTI_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define EXTI_BASE_ADDRESS 0x40010400
|
||||
|
||||
union EXTI_IMR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t MR0:1;
|
||||
uint32_t MR1:1;
|
||||
uint32_t MR2:1;
|
||||
uint32_t MR3:1;
|
||||
uint32_t MR4:1;
|
||||
uint32_t MR5:1;
|
||||
uint32_t MR6:1;
|
||||
uint32_t MR7:1;
|
||||
uint32_t MR8:1;
|
||||
uint32_t MR9:1;
|
||||
uint32_t MR10:1;
|
||||
uint32_t MR11:1;
|
||||
uint32_t MR12:1;
|
||||
uint32_t MR13:1;
|
||||
uint32_t MR14:1;
|
||||
uint32_t MR15:1;
|
||||
uint32_t MR16:1;
|
||||
uint32_t MR17:1;
|
||||
uint32_t MR18:1;
|
||||
uint32_t reserved1:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_IMR_MR0 reg_def( 0, 1)
|
||||
#define EXTI_IMR_MR1 reg_def( 1, 1)
|
||||
#define EXTI_IMR_MR2 reg_def( 2, 1)
|
||||
#define EXTI_IMR_MR3 reg_def( 3, 1)
|
||||
#define EXTI_IMR_MR4 reg_def( 4, 1)
|
||||
#define EXTI_IMR_MR5 reg_def( 5, 1)
|
||||
#define EXTI_IMR_MR6 reg_def( 6, 1)
|
||||
#define EXTI_IMR_MR7 reg_def( 7, 1)
|
||||
#define EXTI_IMR_MR8 reg_def( 8, 1)
|
||||
#define EXTI_IMR_MR9 reg_def( 9, 1)
|
||||
#define EXTI_IMR_MR10 reg_def(10, 1)
|
||||
#define EXTI_IMR_MR11 reg_def(11, 1)
|
||||
#define EXTI_IMR_MR12 reg_def(12, 1)
|
||||
#define EXTI_IMR_MR13 reg_def(13, 1)
|
||||
#define EXTI_IMR_MR14 reg_def(14, 1)
|
||||
#define EXTI_IMR_MR15 reg_def(15, 1)
|
||||
#define EXTI_IMR_MR16 reg_def(16, 1)
|
||||
#define EXTI_IMR_MR17 reg_def(17, 1)
|
||||
#define EXTI_IMR_MR18 reg_def(18, 1)
|
||||
#define EXTI_IMR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_EMR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t MR0:1;
|
||||
uint32_t MR1:1;
|
||||
uint32_t MR2:1;
|
||||
uint32_t MR3:1;
|
||||
uint32_t MR4:1;
|
||||
uint32_t MR5:1;
|
||||
uint32_t MR6:1;
|
||||
uint32_t MR7:1;
|
||||
uint32_t MR8:1;
|
||||
uint32_t MR9:1;
|
||||
uint32_t MR10:1;
|
||||
uint32_t MR11:1;
|
||||
uint32_t MR12:1;
|
||||
uint32_t MR13:1;
|
||||
uint32_t MR14:1;
|
||||
uint32_t MR15:1;
|
||||
uint32_t MR16:1;
|
||||
uint32_t MR17:1;
|
||||
uint32_t MR18:1;
|
||||
uint32_t reserved1:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_EMR_MR0 reg_def( 0, 1)
|
||||
#define EXTI_EMR_MR1 reg_def( 1, 1)
|
||||
#define EXTI_EMR_MR2 reg_def( 2, 1)
|
||||
#define EXTI_EMR_MR3 reg_def( 3, 1)
|
||||
#define EXTI_EMR_MR4 reg_def( 4, 1)
|
||||
#define EXTI_EMR_MR5 reg_def( 5, 1)
|
||||
#define EXTI_EMR_MR6 reg_def( 6, 1)
|
||||
#define EXTI_EMR_MR7 reg_def( 7, 1)
|
||||
#define EXTI_EMR_MR8 reg_def( 8, 1)
|
||||
#define EXTI_EMR_MR9 reg_def( 9, 1)
|
||||
#define EXTI_EMR_MR10 reg_def(10, 1)
|
||||
#define EXTI_EMR_MR11 reg_def(11, 1)
|
||||
#define EXTI_EMR_MR12 reg_def(12, 1)
|
||||
#define EXTI_EMR_MR13 reg_def(13, 1)
|
||||
#define EXTI_EMR_MR14 reg_def(14, 1)
|
||||
#define EXTI_EMR_MR15 reg_def(15, 1)
|
||||
#define EXTI_EMR_MR16 reg_def(16, 1)
|
||||
#define EXTI_EMR_MR17 reg_def(17, 1)
|
||||
#define EXTI_EMR_MR18 reg_def(18, 1)
|
||||
#define EXTI_EMR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_RTSR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t TR0:1;
|
||||
uint32_t TR1:1;
|
||||
uint32_t TR2:1;
|
||||
uint32_t TR3:1;
|
||||
uint32_t TR4:1;
|
||||
uint32_t TR5:1;
|
||||
uint32_t TR6:1;
|
||||
uint32_t TR7:1;
|
||||
uint32_t TR8:1;
|
||||
uint32_t TR9:1;
|
||||
uint32_t TR10:1;
|
||||
uint32_t TR11:1;
|
||||
uint32_t TR12:1;
|
||||
uint32_t TR13:1;
|
||||
uint32_t TR14:1;
|
||||
uint32_t TR15:1;
|
||||
uint32_t TR16:1;
|
||||
uint32_t TR17:1;
|
||||
uint32_t TR18:1;
|
||||
uint32_t reserved1:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_RTSR_TR0 reg_def( 0, 1)
|
||||
#define EXTI_RTSR_TR1 reg_def( 1, 1)
|
||||
#define EXTI_RTSR_TR2 reg_def( 2, 1)
|
||||
#define EXTI_RTSR_TR3 reg_def( 3, 1)
|
||||
#define EXTI_RTSR_TR4 reg_def( 4, 1)
|
||||
#define EXTI_RTSR_TR5 reg_def( 5, 1)
|
||||
#define EXTI_RTSR_TR6 reg_def( 6, 1)
|
||||
#define EXTI_RTSR_TR7 reg_def( 7, 1)
|
||||
#define EXTI_RTSR_TR8 reg_def( 8, 1)
|
||||
#define EXTI_RTSR_TR9 reg_def( 9, 1)
|
||||
#define EXTI_RTSR_TR10 reg_def(10, 1)
|
||||
#define EXTI_RTSR_TR11 reg_def(11, 1)
|
||||
#define EXTI_RTSR_TR12 reg_def(12, 1)
|
||||
#define EXTI_RTSR_TR13 reg_def(13, 1)
|
||||
#define EXTI_RTSR_TR14 reg_def(14, 1)
|
||||
#define EXTI_RTSR_TR15 reg_def(15, 1)
|
||||
#define EXTI_RTSR_TR16 reg_def(16, 1)
|
||||
#define EXTI_RTSR_TR17 reg_def(17, 1)
|
||||
#define EXTI_RTSR_TR18 reg_def(18, 1)
|
||||
#define EXTI_RTSR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_FTSR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t TR0:1;
|
||||
uint32_t TR1:1;
|
||||
uint32_t TR2:1;
|
||||
uint32_t TR3:1;
|
||||
uint32_t TR4:1;
|
||||
uint32_t TR5:1;
|
||||
uint32_t TR6:1;
|
||||
uint32_t TR7:1;
|
||||
uint32_t TR8:1;
|
||||
uint32_t TR9:1;
|
||||
uint32_t TR10:1;
|
||||
uint32_t TR11:1;
|
||||
uint32_t TR12:1;
|
||||
uint32_t TR13:1;
|
||||
uint32_t TR14:1;
|
||||
uint32_t TR15:1;
|
||||
uint32_t TR16:1;
|
||||
uint32_t TR17:1;
|
||||
uint32_t TR18:1;
|
||||
uint32_t reserved1:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_FTSR_TR0 reg_def( 0, 1)
|
||||
#define EXTI_FTSR_TR1 reg_def( 1, 1)
|
||||
#define EXTI_FTSR_TR2 reg_def( 2, 1)
|
||||
#define EXTI_FTSR_TR3 reg_def( 3, 1)
|
||||
#define EXTI_FTSR_TR4 reg_def( 4, 1)
|
||||
#define EXTI_FTSR_TR5 reg_def( 5, 1)
|
||||
#define EXTI_FTSR_TR6 reg_def( 6, 1)
|
||||
#define EXTI_FTSR_TR7 reg_def( 7, 1)
|
||||
#define EXTI_FTSR_TR8 reg_def( 8, 1)
|
||||
#define EXTI_FTSR_TR9 reg_def( 9, 1)
|
||||
#define EXTI_FTSR_TR10 reg_def(10, 1)
|
||||
#define EXTI_FTSR_TR11 reg_def(11, 1)
|
||||
#define EXTI_FTSR_TR12 reg_def(12, 1)
|
||||
#define EXTI_FTSR_TR13 reg_def(13, 1)
|
||||
#define EXTI_FTSR_TR14 reg_def(14, 1)
|
||||
#define EXTI_FTSR_TR15 reg_def(15, 1)
|
||||
#define EXTI_FTSR_TR16 reg_def(16, 1)
|
||||
#define EXTI_FTSR_TR17 reg_def(17, 1)
|
||||
#define EXTI_FTSR_TR18 reg_def(18, 1)
|
||||
#define EXTI_FTSR_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_SWIER {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t SWIER0:1;
|
||||
uint32_t SWIER1:1;
|
||||
uint32_t SWIER2:1;
|
||||
uint32_t SWIER3:1;
|
||||
uint32_t SWIER4:1;
|
||||
uint32_t SWIER5:1;
|
||||
uint32_t SWIER6:1;
|
||||
uint32_t SWIER7:1;
|
||||
uint32_t SWIER8:1;
|
||||
uint32_t SWIER9:1;
|
||||
uint32_t SWIER10:1;
|
||||
uint32_t SWIER11:1;
|
||||
uint32_t SWIER12:1;
|
||||
uint32_t SWIER13:1;
|
||||
uint32_t SWIER14:1;
|
||||
uint32_t SWIER15:1;
|
||||
uint32_t SWIER16:1;
|
||||
uint32_t SWIER17:1;
|
||||
uint32_t SWIER18:1;
|
||||
uint32_t reserved1:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_SWIER_SWIER0 reg_def( 0, 1)
|
||||
#define EXTI_SWIER_SWIER1 reg_def( 1, 1)
|
||||
#define EXTI_SWIER_SWIER2 reg_def( 2, 1)
|
||||
#define EXTI_SWIER_SWIER3 reg_def( 3, 1)
|
||||
#define EXTI_SWIER_SWIER4 reg_def( 4, 1)
|
||||
#define EXTI_SWIER_SWIER5 reg_def( 5, 1)
|
||||
#define EXTI_SWIER_SWIER6 reg_def( 6, 1)
|
||||
#define EXTI_SWIER_SWIER7 reg_def( 7, 1)
|
||||
#define EXTI_SWIER_SWIER8 reg_def( 8, 1)
|
||||
#define EXTI_SWIER_SWIER9 reg_def( 9, 1)
|
||||
#define EXTI_SWIER_SWIER10 reg_def(10, 1)
|
||||
#define EXTI_SWIER_SWIER11 reg_def(11, 1)
|
||||
#define EXTI_SWIER_SWIER12 reg_def(12, 1)
|
||||
#define EXTI_SWIER_SWIER13 reg_def(13, 1)
|
||||
#define EXTI_SWIER_SWIER14 reg_def(14, 1)
|
||||
#define EXTI_SWIER_SWIER15 reg_def(15, 1)
|
||||
#define EXTI_SWIER_SWIER16 reg_def(16, 1)
|
||||
#define EXTI_SWIER_SWIER17 reg_def(17, 1)
|
||||
#define EXTI_SWIER_SWIER18 reg_def(18, 1)
|
||||
#define EXTI_SWIER_reserved1 reg_def(19, 13)
|
||||
|
||||
union EXTI_PR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t PR0:1;
|
||||
uint32_t PR1:1;
|
||||
uint32_t PR2:1;
|
||||
uint32_t PR3:1;
|
||||
uint32_t PR4:1;
|
||||
uint32_t PR5:1;
|
||||
uint32_t PR6:1;
|
||||
uint32_t PR7:1;
|
||||
uint32_t PR8:1;
|
||||
uint32_t PR9:1;
|
||||
uint32_t PR10:1;
|
||||
uint32_t PR11:1;
|
||||
uint32_t PR12:1;
|
||||
uint32_t PR13:1;
|
||||
uint32_t PR14:1;
|
||||
uint32_t PR15:1;
|
||||
uint32_t PR16:1;
|
||||
uint32_t PR17:1;
|
||||
uint32_t PR18:1;
|
||||
uint32_t reserved1:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define EXTI_PR_PR0 reg_def( 0, 1)
|
||||
#define EXTI_PR_PR1 reg_def( 1, 1)
|
||||
#define EXTI_PR_PR2 reg_def( 2, 1)
|
||||
#define EXTI_PR_PR3 reg_def( 3, 1)
|
||||
#define EXTI_PR_PR4 reg_def( 4, 1)
|
||||
#define EXTI_PR_PR5 reg_def( 5, 1)
|
||||
#define EXTI_PR_PR6 reg_def( 6, 1)
|
||||
#define EXTI_PR_PR7 reg_def( 7, 1)
|
||||
#define EXTI_PR_PR8 reg_def( 8, 1)
|
||||
#define EXTI_PR_PR9 reg_def( 9, 1)
|
||||
#define EXTI_PR_PR10 reg_def(10, 1)
|
||||
#define EXTI_PR_PR11 reg_def(11, 1)
|
||||
#define EXTI_PR_PR12 reg_def(12, 1)
|
||||
#define EXTI_PR_PR13 reg_def(13, 1)
|
||||
#define EXTI_PR_PR14 reg_def(14, 1)
|
||||
#define EXTI_PR_PR15 reg_def(15, 1)
|
||||
#define EXTI_PR_PR16 reg_def(16, 1)
|
||||
#define EXTI_PR_PR17 reg_def(17, 1)
|
||||
#define EXTI_PR_PR18 reg_def(18, 1)
|
||||
#define EXTI_PR_reserved1 reg_def(19, 13)
|
||||
|
||||
struct __attribute__((packed)) EXTI {
|
||||
union EXTI_IMR IMR;
|
||||
union EXTI_EMR EMR;
|
||||
union EXTI_RTSR RTSR;
|
||||
union EXTI_FTSR FTSR;
|
||||
union EXTI_SWIER SWIER;
|
||||
union EXTI_PR PR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_EXTI_REGS_H_
|
||||
|
||||
54
drv/flash.c
Normal file
54
drv/flash.c
Normal file
@ -0,0 +1,54 @@
|
||||
/** @file flash.c
|
||||
* Module handling flash memory interface registers.
|
||||
*
|
||||
* The module provides functions to configure the flash and perform read and
|
||||
* writes
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "flash.h"
|
||||
#include "flash_regs.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct FLASH* regs = (struct FLASH*)FLASH_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the correct latency to compensate the core's clock speed. Latency must
|
||||
* never be too low or the system will crash due to errors when accessing the
|
||||
* flash, hence the warning in the header
|
||||
*/
|
||||
void flash_configure(enum FlashPreset preset)
|
||||
{
|
||||
//restore default configuration
|
||||
regs->ACR.word &= ~0x3f;
|
||||
regs->ACR.word |= 0x30;
|
||||
|
||||
//apply new configuration
|
||||
switch (preset) {
|
||||
case FLASH_PRESET_LOW_CLOCK_SPEED:
|
||||
reg_set(regs->ACR, FLASH_ACR_HLFCYA); //half cycle for power saving
|
||||
break;
|
||||
case FLASH_PRESET_MEDIUM_CLOCK_SPEED:
|
||||
reg_reset(regs->ACR, FLASH_ACR_LATENCY);
|
||||
reg_write(regs->ACR, FLASH_ACR_LATENCY, 0x1);
|
||||
break;
|
||||
case FLASH_PRESET_HIGH_CLOCK_SPEED:
|
||||
reg_reset(regs->ACR, FLASH_ACR_LATENCY);
|
||||
reg_write(regs->ACR, FLASH_ACR_LATENCY, 0x2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
39
drv/flash.h
Normal file
39
drv/flash.h
Normal file
@ -0,0 +1,39 @@
|
||||
/** @file flash.h
|
||||
* Module handling flash memory interface registers.
|
||||
*
|
||||
* The module provides functions to configure the flash and perform read and
|
||||
* writes
|
||||
*/
|
||||
|
||||
#ifndef _FLASH_H_
|
||||
#define _FLASH_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available flash configuration presets
|
||||
*/
|
||||
enum FlashPreset {
|
||||
FLASH_PRESET_LOW_CLOCK_SPEED, //for 0 < clock <= 24Mz
|
||||
FLASH_PRESET_MEDIUM_CLOCK_SPEED, //for 24MHz < clock <= 48MHz
|
||||
FLASH_PRESET_HIGH_CLOCK_SPEED, //for 48MHz < clock <= 72MHz
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configure the flash according to the given preset. Warning: calling this
|
||||
* function with a sysclk higher than 24Mhz may cause the system to crash,
|
||||
* please lower the clocks first
|
||||
*/
|
||||
void flash_configure(enum FlashPreset preset);
|
||||
|
||||
|
||||
#endif //_FLASH_H_
|
||||
|
||||
105
drv/flash_regs.h
Normal file
105
drv/flash_regs.h
Normal file
@ -0,0 +1,105 @@
|
||||
/** @file flash_regs.h
|
||||
* Module defining flash memory interface registers.
|
||||
*
|
||||
* Mainly made to be used by the rcc module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _FLASH_REGS_H_
|
||||
#define _FLASH_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define FLASH_BASE_ADDRESS 0x40022000
|
||||
|
||||
union FLASH_ACR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t LATENCY:3;
|
||||
uint32_t HLFCYA:1;
|
||||
uint32_t PRFTBE:1;
|
||||
uint32_t PRFTBS:1;
|
||||
uint32_t reserved1:26;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define FLASH_ACR_LATENCY reg_def(0, 3)
|
||||
#define FLASH_ACR_HLFCYA reg_def(3, 1)
|
||||
#define FLASH_ACR_PRFTBE reg_def(4, 1)
|
||||
#define FLASH_ACR_PRFTBS reg_def(5, 1)
|
||||
#define FLASH_ACR_reserved1 reg_def(6, 26)
|
||||
|
||||
union FLASH_KEYR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_OPTKEYR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_SR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_CR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_AR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_OBR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_WRPR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) FLASH {
|
||||
union FLASH_ACR ACR;
|
||||
union FLASH_KEYR KEYR;
|
||||
union FLASH_OPTKEYR OPTKEYR;
|
||||
union FLASH_SR SR;
|
||||
union FLASH_CR CR;
|
||||
union FLASH_AR AR;
|
||||
uint32_t reserved1;
|
||||
union FLASH_OBR OBR;
|
||||
union FLASH_WRPR WRPR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_FLASH_REGS_H_
|
||||
|
||||
95
drv/gpio.c
Normal file
95
drv/gpio.c
Normal file
@ -0,0 +1,95 @@
|
||||
/** @file gpio.c
|
||||
* Module handling General Purpose Input/Output (GPIO) pins
|
||||
*
|
||||
* The module provides functions to configure the gpio pins and read from/
|
||||
* write to them
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "gpio.h"
|
||||
#include "gpio_regs.h"
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct GPIO* regs = (struct GPIO*)GPIO_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Use the provided mask to generate its equivalent with 3 bits of padding
|
||||
* between each initial bit. This new mask matches the registers layout and
|
||||
* allow for direct application of the mode and config. Outputs are disabled
|
||||
* prior to confiiguration to avoid any glitches. The relevant clocks are
|
||||
* automatically enabled for the ports used
|
||||
*/
|
||||
void gpio_configure(enum GpioPort port, enum GpioPin pin_mask,
|
||||
enum GpioMode mode, enum GpioConfig config)
|
||||
{
|
||||
//ensure gpio port is enabled
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_NONE, RCC_APB2_IOPA << port);
|
||||
|
||||
//reset outputs before configuring anything
|
||||
regs->PORTS[port].BRR.word = pin_mask;
|
||||
|
||||
//clear config for selected port, then apply new config, 8 first pins
|
||||
uint32_t mask = 0;
|
||||
for (uint8_t i=0; i<8; ++i)
|
||||
{
|
||||
if (pin_mask & (0x1 << i))
|
||||
{
|
||||
mask |= 0x1 << (i * 4);
|
||||
}
|
||||
}
|
||||
regs->PORTS[port].CRL.word &= ~(0xF * mask);
|
||||
regs->PORTS[port].CRL.word |= ((config << 2) | (mode << 0)) * mask;
|
||||
|
||||
//clear config for selected port, then apply new config, 8 last pins
|
||||
mask = 0;
|
||||
pin_mask = pin_mask >> 8;
|
||||
for (uint8_t i=0; i<8; ++i)
|
||||
{
|
||||
if (pin_mask & (0x1 << i))
|
||||
{
|
||||
mask |= 0x1 << (i * 4);
|
||||
}
|
||||
}
|
||||
regs->PORTS[port].CRH.word &= ~(0xF * mask);
|
||||
regs->PORTS[port].CRH.word |= ((config << 2) | (mode << 0)) * mask;
|
||||
}
|
||||
|
||||
void gpio_reset(enum GpioPort port, enum GpioPin pin_mask)
|
||||
{
|
||||
gpio_configure(port, pin_mask, GPIO_MODE_INPUT, GPIO_CONFIG_IN_FLOATING);
|
||||
}
|
||||
|
||||
void gpio_write(enum GpioPort port, enum GpioPin pin_mask, bool value)
|
||||
{
|
||||
if (value) {
|
||||
regs->PORTS[port].BSRR.word = pin_mask;
|
||||
} else {
|
||||
regs->PORTS[port].BRR.word = pin_mask;
|
||||
}
|
||||
}
|
||||
|
||||
bool gpio_read(enum GpioPort port, enum GpioPin pin_mask)
|
||||
{
|
||||
return (regs->PORTS[port].IDR.word & pin_mask) == pin_mask;
|
||||
}
|
||||
|
||||
void gpio_reset_peripheral(void)
|
||||
{
|
||||
rcc_disable(RCC_AHB_NONE, RCC_APB1_NONE, RCC_APB2_IOPA | RCC_APB2_IOPB
|
||||
| RCC_APB2_IOPC | RCC_APB2_IOPD | RCC_APB2_IOPE | RCC_APB2_IOPF
|
||||
| RCC_APB2_IOPG);
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
125
drv/gpio.h
Normal file
125
drv/gpio.h
Normal file
@ -0,0 +1,125 @@
|
||||
/** @file gpio.h
|
||||
* Module handling General Purpose Input/Output (GPIO) pins
|
||||
*
|
||||
* The module provides functions to configure the gpio pins and read from/
|
||||
* write to them
|
||||
*/
|
||||
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available GPIO ports. Note that not all ports may be available for a
|
||||
* particular chip
|
||||
*/
|
||||
enum GpioPort {
|
||||
GPIO_PORT_A = 0,
|
||||
GPIO_PORT_B,
|
||||
GPIO_PORT_C,
|
||||
GPIO_PORT_D,
|
||||
GPIO_PORT_E,
|
||||
GPIO_PORT_F,
|
||||
GPIO_PORT_G,
|
||||
};
|
||||
|
||||
/**
|
||||
* Availables pin for a particular port. Note that all ports available may not
|
||||
* have all the pins listed here and that some pins may be used by defaut (jtag,
|
||||
* ...)
|
||||
*/
|
||||
enum GpioPin {
|
||||
GPIO_PIN_0 = (0x1 << 0),
|
||||
GPIO_PIN_1 = (0x1 << 1),
|
||||
GPIO_PIN_2 = (0x1 << 2),
|
||||
GPIO_PIN_3 = (0x1 << 3),
|
||||
GPIO_PIN_4 = (0x1 << 4),
|
||||
GPIO_PIN_5 = (0x1 << 5),
|
||||
GPIO_PIN_6 = (0x1 << 6),
|
||||
GPIO_PIN_7 = (0x1 << 7),
|
||||
GPIO_PIN_8 = (0x1 << 8),
|
||||
GPIO_PIN_9 = (0x1 << 9),
|
||||
GPIO_PIN_10 = (0x1 << 10),
|
||||
GPIO_PIN_11 = (0x1 << 11),
|
||||
GPIO_PIN_12 = (0x1 << 12),
|
||||
GPIO_PIN_13 = (0x1 << 13),
|
||||
GPIO_PIN_14 = (0x1 << 14),
|
||||
GPIO_PIN_15 = (0x1 << 15),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available modes for a pin. To have a pin in both modes simultaneously, use
|
||||
* push-pull configuration in input mode but note that the power may be
|
||||
* limited
|
||||
*/
|
||||
enum GpioMode {
|
||||
GPIO_MODE_INPUT = 0,
|
||||
GPIO_MODE_OUTPUT, //10MHz max
|
||||
GPIO_MODE_OUTPUT_SLOW, //2MHz max
|
||||
GPIO_MODE_OUTPUT_FAST, //50MHz max
|
||||
};
|
||||
|
||||
/**
|
||||
* Available configurations for a pin. Some configurations only apply in input
|
||||
* mode (denoted "IN") while others only apply in output mode (denoted "OUT")
|
||||
*/
|
||||
enum GpioConfig {
|
||||
GPIO_CONFIG_IN_ANALOG = 0,
|
||||
GPIO_CONFIG_IN_FLOATING,
|
||||
GPIO_CONFIG_IN_PUSH_PULL, //use gpio_write() to configure pull_up/down
|
||||
GPIO_CONFIG_OUT_PUSH_PULL = 0,
|
||||
GPIO_CONFIG_OUT_OPEN_DRAIN,
|
||||
GPIO_CONFIG_OUT_ALT_PUSH_PULL,
|
||||
GPIO_CONFIG_OUT_ALT_OPEN_DRAIN,
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures gpio pins on a single port. The GpioPin enum can be used as mask
|
||||
* to configure multiple pins at the same time. Before configuring a pin, make
|
||||
* sure it isn't used somewhere else (peripherals, jtag, ...). After
|
||||
* configuration, the selected output pins are set to output 0V
|
||||
*/
|
||||
void gpio_configure(enum GpioPort port, enum GpioPin pin_mask,
|
||||
enum GpioMode mode, enum GpioConfig config);
|
||||
|
||||
/**
|
||||
* Resets gpio pins on a single port. The GpioPin enum can be used as mask
|
||||
* to reset multiple pins at the same time. This is a simple wrapper over
|
||||
* gpio_configure(), setting the selected ports as floating input
|
||||
*/
|
||||
void gpio_reset(enum GpioPort port, enum GpioPin pin_mask);
|
||||
|
||||
/**
|
||||
* Write a value to output gpios on a single port. The GpioPin enum can be used
|
||||
* as mask to reset multiple pins at the same time. In push-pull input mode,
|
||||
* configure the pull up/down. Has no effect otherwise. Writes are atomic
|
||||
* operations
|
||||
*/
|
||||
void gpio_write(enum GpioPort port, enum GpioPin pin_mask, bool value);
|
||||
|
||||
/**
|
||||
* Reads the value of gpios on a single port. The GpioPin enum can be used
|
||||
* as mask to read multiple pins at the same time. For output pins, reads the
|
||||
* pin state. Returns true if all selected ports are high
|
||||
*/
|
||||
bool gpio_read(enum GpioPort port, enum GpioPin pin_mask);
|
||||
|
||||
/**
|
||||
* Resets all gpios and disable all ports. The gpio peripherals are returned to
|
||||
* their reset configuration and their respective clocks disabled
|
||||
*/
|
||||
void gpio_reset_peripheral(void);
|
||||
|
||||
|
||||
#endif //_GPIO_H_
|
||||
|
||||
215
drv/gpio_regs.h
Normal file
215
drv/gpio_regs.h
Normal file
@ -0,0 +1,215 @@
|
||||
/** @file gpio_regs.h
|
||||
* Module defining the GPIO registers.
|
||||
*
|
||||
* Mainly made to be used by the gpio module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _GPIO_REGS_H_
|
||||
#define _GPIO_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define GPIO_BASE_ADDRESS 0x40010800
|
||||
|
||||
union GPIO_CRL {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t MODE0:2;
|
||||
uint32_t CNF0:2;
|
||||
uint32_t MODE1:2;
|
||||
uint32_t CNF1:2;
|
||||
uint32_t MODE2:2;
|
||||
uint32_t CNF2:2;
|
||||
uint32_t MODE3:2;
|
||||
uint32_t CNF3:2;
|
||||
uint32_t MODE4:2;
|
||||
uint32_t CNF4:2;
|
||||
uint32_t MODE5:2;
|
||||
uint32_t CNF5:2;
|
||||
uint32_t MODE6:2;
|
||||
uint32_t CNF6:2;
|
||||
uint32_t MODE7:2;
|
||||
uint32_t CNF7:2;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union GPIO_CRH {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t MODE8:2;
|
||||
uint32_t CNF8:2;
|
||||
uint32_t MODE9:2;
|
||||
uint32_t CNF9:2;
|
||||
uint32_t MODE10:2;
|
||||
uint32_t CNF10:2;
|
||||
uint32_t MODE11:2;
|
||||
uint32_t CNF11:2;
|
||||
uint32_t MODE12:2;
|
||||
uint32_t CNF12:2;
|
||||
uint32_t MODE13:2;
|
||||
uint32_t CNF13:2;
|
||||
uint32_t MODE14:2;
|
||||
uint32_t CNF14:2;
|
||||
uint32_t MODE15:2;
|
||||
uint32_t CNF15:2;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union GPIO_IDR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t IDR0:1;
|
||||
uint32_t IDR1:1;
|
||||
uint32_t IDR2:1;
|
||||
uint32_t IDR3:1;
|
||||
uint32_t IDR4:1;
|
||||
uint32_t IDR5:1;
|
||||
uint32_t IDR6:1;
|
||||
uint32_t IDR7:1;
|
||||
uint32_t IDR8:1;
|
||||
uint32_t IDR9:1;
|
||||
uint32_t IDR10:1;
|
||||
uint32_t IDR11:1;
|
||||
uint32_t IDR12:1;
|
||||
uint32_t IDR13:1;
|
||||
uint32_t IDR14:1;
|
||||
uint32_t IDR15:1;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union GPIO_ODR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t ODR0:1;
|
||||
uint32_t ODR1:1;
|
||||
uint32_t ODR2:1;
|
||||
uint32_t ODR3:1;
|
||||
uint32_t ODR4:1;
|
||||
uint32_t ODR5:1;
|
||||
uint32_t ODR6:1;
|
||||
uint32_t ODR7:1;
|
||||
uint32_t ODR8:1;
|
||||
uint32_t ODR9:1;
|
||||
uint32_t ODR10:1;
|
||||
uint32_t ODR11:1;
|
||||
uint32_t ODR12:1;
|
||||
uint32_t ODR13:1;
|
||||
uint32_t ODR14:1;
|
||||
uint32_t ODR15:1;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union GPIO_BSRR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t BS0:1;
|
||||
uint32_t BS1:1;
|
||||
uint32_t BS2:1;
|
||||
uint32_t BS3:1;
|
||||
uint32_t BS4:1;
|
||||
uint32_t BS5:1;
|
||||
uint32_t BS6:1;
|
||||
uint32_t BS7:1;
|
||||
uint32_t BS8:1;
|
||||
uint32_t BS9:1;
|
||||
uint32_t BS10:1;
|
||||
uint32_t BS11:1;
|
||||
uint32_t BS12:1;
|
||||
uint32_t BS13:1;
|
||||
uint32_t BS14:1;
|
||||
uint32_t BS15:1;
|
||||
uint32_t BR0:1;
|
||||
uint32_t BR1:1;
|
||||
uint32_t BR2:1;
|
||||
uint32_t BR3:1;
|
||||
uint32_t BR4:1;
|
||||
uint32_t BR5:1;
|
||||
uint32_t BR6:1;
|
||||
uint32_t BR7:1;
|
||||
uint32_t BR8:1;
|
||||
uint32_t BR9:1;
|
||||
uint32_t BR10:1;
|
||||
uint32_t BR11:1;
|
||||
uint32_t BR12:1;
|
||||
uint32_t BR13:1;
|
||||
uint32_t BR14:1;
|
||||
uint32_t BR15:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union GPIO_BRR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t BR0:1;
|
||||
uint32_t BR1:1;
|
||||
uint32_t BR2:1;
|
||||
uint32_t BR3:1;
|
||||
uint32_t BR4:1;
|
||||
uint32_t BR5:1;
|
||||
uint32_t BR6:1;
|
||||
uint32_t BR7:1;
|
||||
uint32_t BR8:1;
|
||||
uint32_t BR9:1;
|
||||
uint32_t BR10:1;
|
||||
uint32_t BR11:1;
|
||||
uint32_t BR12:1;
|
||||
uint32_t BR13:1;
|
||||
uint32_t BR14:1;
|
||||
uint32_t BR15:1;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union GPIO_LCKK {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t LCK0:1;
|
||||
uint32_t LCK1:1;
|
||||
uint32_t LCK2:1;
|
||||
uint32_t LCK3:1;
|
||||
uint32_t LCK4:1;
|
||||
uint32_t LCK5:1;
|
||||
uint32_t LCK6:1;
|
||||
uint32_t LCK7:1;
|
||||
uint32_t LCK8:1;
|
||||
uint32_t LCK9:1;
|
||||
uint32_t LCK10:1;
|
||||
uint32_t LCK11:1;
|
||||
uint32_t LCK12:1;
|
||||
uint32_t LCK13:1;
|
||||
uint32_t LCK14:1;
|
||||
uint32_t LCK15:1;
|
||||
uint32_t LCKK:1;
|
||||
uint32_t reserved1:15;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) GPIO_PORT {
|
||||
union GPIO_CRL CRL;
|
||||
union GPIO_CRH CRH;
|
||||
union GPIO_IDR IDR;
|
||||
union GPIO_ODR ODR;
|
||||
union GPIO_BSRR BSRR;
|
||||
union GPIO_BRR BRR;
|
||||
union GPIO_LCKK LCKK;
|
||||
uint32_t reserved1[249];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) GPIO {
|
||||
struct GPIO_PORT PORTS[7];
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_GPIO_REGS_H_
|
||||
|
||||
87
drv/nvic.c
Normal file
87
drv/nvic.c
Normal file
@ -0,0 +1,87 @@
|
||||
/** @file nvic.c
|
||||
* Module handling the Nested Vector Interrupt Controller (NVIC)
|
||||
*
|
||||
* The module provides functions to configure the different interrupts and
|
||||
* their priority suiing the NVIC's interface
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "nvic.h"
|
||||
#include "nvic_regs.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* NVIC's register are only accessible by 32 bits words, and data is stored
|
||||
* accors 3 consecutive registers. This macro sets the right bit from the
|
||||
* right register based on the IRQ number
|
||||
*/
|
||||
#define set_bit(reg, irq) \
|
||||
do { \
|
||||
uint8_t n = irq / 32; \
|
||||
uint8_t r = irq - n * 32; \
|
||||
regs->reg[n] |= (0x1 << r); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* NVIC's register are only accessible by 32 bits words, and data is stored
|
||||
* accors 3 consecutive registers. This macro fetches the right bit from the
|
||||
* right register based on the IRQ number
|
||||
*/
|
||||
#define get_bit(reg, irq, res) \
|
||||
do { \
|
||||
uint8_t n = irq / 32; \
|
||||
uint8_t r = irq - n * 32; \
|
||||
res = 0 != (regs->reg[n] | (0x1 << r)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct NVIC1* regs = (struct NVIC1*)NVIC1_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void nvic_enable(enum NvicIrq irq)
|
||||
{
|
||||
set_bit(ISERX, irq);
|
||||
}
|
||||
|
||||
void nvic_disable(enum NvicIrq irq)
|
||||
{
|
||||
set_bit(ICERX, irq);
|
||||
}
|
||||
|
||||
void nvic_clear_pending(enum NvicIrq irq)
|
||||
{
|
||||
set_bit(ICPRX, irq);
|
||||
}
|
||||
|
||||
void nvic_set_priority(enum NvicIrq irq, uint8_t priority)
|
||||
{
|
||||
uint8_t n = irq / 4;
|
||||
uint8_t r = (irq - n * 4); //get the division's reminder
|
||||
r *= 8; //mul by 8 since each 'slot' is 8 bits
|
||||
r += 4; //add 4 since we only write to the upper 4 bits
|
||||
regs->IPRX[n] &= ~(0x0F << r);
|
||||
regs->IPRX[n] |= (priority & 0x0F) << r;
|
||||
}
|
||||
|
||||
void nvic_set_pending(enum NvicIrq irq)
|
||||
{
|
||||
set_bit(ISPRX, irq);
|
||||
}
|
||||
|
||||
bool nvic_is_pending(enum NvicIrq irq)
|
||||
{
|
||||
bool res = false;
|
||||
get_bit(ISPRX, irq, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
125
drv/nvic.h
Normal file
125
drv/nvic.h
Normal file
@ -0,0 +1,125 @@
|
||||
/** @file nvic.h
|
||||
* Module handling the Nested Vector Interrupt Controller (NVIC)
|
||||
*
|
||||
* The module provides functions to configure the different interrupts and
|
||||
* their priority suiing the NVIC's interface
|
||||
*/
|
||||
|
||||
#ifndef _NVIC_H_
|
||||
#define _NVIC_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available System IRQs. This does not include CPU's IRQs
|
||||
*/
|
||||
enum NvicIrq {
|
||||
NVIC_IRQ_WWDG = 0,
|
||||
NVIC_IRQ_PVD,
|
||||
NVIC_IRQ_TAMPER,
|
||||
NVIC_IRQ_RTC,
|
||||
NVIC_IRQ_FLASH,
|
||||
NVIC_IRQ_RCC,
|
||||
NVIC_IRQ_EXTI0,
|
||||
NVIC_IRQ_EXTI1,
|
||||
NVIC_IRQ_EXTI2,
|
||||
NVIC_IRQ_EXTI3,
|
||||
NVIC_IRQ_EXTI4,
|
||||
NVIC_IRQ_DMA1_CHANNEL1,
|
||||
NVIC_IRQ_DMA1_CHANNEL2,
|
||||
NVIC_IRQ_DMA1_CHANNEL3,
|
||||
NVIC_IRQ_DMA1_CHANNEL4,
|
||||
NVIC_IRQ_DMA1_CHANNEL5,
|
||||
NVIC_IRQ_DMA1_CHANNEL6,
|
||||
NVIC_IRQ_DMA1_CHANNEL7,
|
||||
NVIC_IRQ_ADC1_2,
|
||||
NVIC_IRQ_HP_CAN_TX,
|
||||
NVIC_IRQ_LP_CAN_RX0,
|
||||
NVIC_IRQ_CAN_RX1,
|
||||
NVIC_IRQ_CAN_SCE,
|
||||
NVIC_IRQ_EXTI9_5,
|
||||
NVIC_IRQ_TIM1_BRK,
|
||||
NVIC_IRQ_TIM1_UP,
|
||||
NVIC_IRQ_TIM1_TRG_COM,
|
||||
NVIC_IRQ_TIM1_CC,
|
||||
NVIC_IRQ_TIM2,
|
||||
NVIC_IRQ_TIM3,
|
||||
NVIC_IRQ_TIM4,
|
||||
NVIC_IRQ_I2C1_EVENT,
|
||||
NVIC_IRQ_I2C1_ERROR,
|
||||
NVIC_IRQ_I2C2_EVENT,
|
||||
NVIC_IRQ_I2C2_ERROR,
|
||||
NVIC_IRQ_SPI1,
|
||||
NVIC_IRQ_SPI2,
|
||||
NVIC_IRQ_USART1,
|
||||
NVIC_IRQ_USART2,
|
||||
NVIC_IRQ_USART3,
|
||||
NVIC_IRQ_EXTI15_10,
|
||||
NVIC_IRQ_RTC_ALARM,
|
||||
NVIC_IRQ_USB_WAKEUP,
|
||||
NVIC_IRQ_TIM8_BRK,
|
||||
NVIC_IRQ_TIM8_UP,
|
||||
NVIC_IRQ_TIM8_TRG_COM,
|
||||
NVIC_IRQ_TIM8_CC,
|
||||
NVIC_IRQ_ADC3,
|
||||
NVIC_IRQ_FSMC,
|
||||
NVIC_IRQ_SDIO,
|
||||
NVIC_IRQ_TIM5,
|
||||
NVIC_IRQ_SPI3,
|
||||
NVIC_IRQ_UART4,
|
||||
NVIC_IRQ_UART5,
|
||||
NVIC_IRQ_TIM6,
|
||||
NVIC_IRQ_TIM7,
|
||||
NVIC_IRQ_DMA2_CHANNEL1,
|
||||
NVIC_IRQ_DMA2_CHANNEL2,
|
||||
NVIC_IRQ_DMA2_CHANNEL3,
|
||||
NVIC_IRQ_DMA2_CHANNEL4_5,
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Enables the selected IRQ
|
||||
*/
|
||||
void nvic_enable(enum NvicIrq irq);
|
||||
|
||||
/**
|
||||
* Disables the selected IRQ
|
||||
*/
|
||||
void nvic_disable(enum NvicIrq irq);
|
||||
|
||||
/**
|
||||
* Clears the pending state of an IRQ. Should be called when reaching an IRQ
|
||||
* handler so that the IRQ isn't triggered again when exiting the handler
|
||||
*/
|
||||
void nvic_clear_pending(enum NvicIrq irq);
|
||||
|
||||
/**
|
||||
* Sets the priority for the selected IRQ. The lower the priority value, the
|
||||
* higher the effective priority. Valid priority values range from 0 to 15. Any
|
||||
* higher value will be ignored. When multiple IRQs with the same priority are
|
||||
* triggered, they will be serviced from the lowest ID to the highest
|
||||
*/
|
||||
void nvic_set_priority(enum NvicIrq irq, uint8_t priority);
|
||||
|
||||
/**
|
||||
* Sets the selected IRQ's pending state. If the IRQ is active, it will be
|
||||
* triggered
|
||||
*/
|
||||
void nvic_set_pending(enum NvicIrq irq);
|
||||
|
||||
/**
|
||||
* Returns wether the selected IRQ is currently pending or not
|
||||
*/
|
||||
bool nvic_is_pending(enum NvicIrq irq);
|
||||
|
||||
|
||||
#endif //_RCC_H_
|
||||
|
||||
39
drv/nvic_regs.h
Normal file
39
drv/nvic_regs.h
Normal file
@ -0,0 +1,39 @@
|
||||
/** @file nvic_regs.h
|
||||
* Module defining the Nested Vector Interrupt Controller (NVIC) registers.
|
||||
*
|
||||
* Mainly made to be used by the nvic module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _NVIC_REGS_H_
|
||||
#define _NVIC_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define NVIC1_BASE_ADDRESS 0xE000E100
|
||||
#define NVIC2_BASE_ADDRESS 0xE000EF00
|
||||
|
||||
struct __attribute__((packed)) NVIC1 {
|
||||
uint32_t ISERX[3];
|
||||
uint32_t ICERX[3];
|
||||
uint32_t ISPRX[3];
|
||||
uint32_t ICPRX[3];
|
||||
uint32_t IABRX[3];
|
||||
uint32_t IPRX[20];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) NVIC2 {
|
||||
uint32_t INTID;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_NVIC_REGS_H_
|
||||
|
||||
183
drv/rcc.c
Normal file
183
drv/rcc.c
Normal file
@ -0,0 +1,183 @@
|
||||
/** @file rcc.c
|
||||
* Module handling Reset and Clocks Control (RCC).
|
||||
*
|
||||
* The module provides functions to configure clocks according to presets as
|
||||
* well as to enable/disable/reset peripherals.
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "rcc.h"
|
||||
#include "rcc_regs.h"
|
||||
#include "flash.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
#define AHB_MASK 0x00000557
|
||||
#define APB1_MASK 0x3afec9ff
|
||||
#define APB2_MASK 0x0038fffd
|
||||
|
||||
static void apply_default_preset(void);
|
||||
static void apply_speed_preset(void);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct RCC* regs = (struct RCC*)RCC_BASE_ADDRESS;
|
||||
static enum RccPreset current_preset = RCC_PRESET_DEFAULT;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the clock sources, PLL, prescalers, etc. All peripherals are
|
||||
* disabled prior to any modifications to avoid unwanted side effects.
|
||||
*/
|
||||
void rcc_configure(enum RccPreset preset)
|
||||
{
|
||||
//disable all peripherals during clock configuration
|
||||
union RCC_APB1ENR apb1_enr = regs->APB1ENR;
|
||||
regs->APB1ENR.word = 0x0;
|
||||
union RCC_APB2ENR apb2_enr = regs->APB2ENR;
|
||||
regs->APB2ENR.word = 0x0;
|
||||
|
||||
switch (preset) {
|
||||
case RCC_PRESET_DEFAULT:
|
||||
apply_default_preset();
|
||||
current_preset = RCC_PRESET_DEFAULT;
|
||||
break;
|
||||
case RCC_PRESET_SPEED:
|
||||
apply_speed_preset();
|
||||
current_preset = RCC_PRESET_SPEED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//re-enable peripherals
|
||||
regs->APB1ENR = apb1_enr;
|
||||
regs->APB2ENR = apb2_enr;
|
||||
}
|
||||
|
||||
void rcc_enable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
|
||||
enum RccApb2 apb2_mask)
|
||||
{
|
||||
regs->AHBENR.word |= ahb_mask & AHB_MASK;
|
||||
regs->APB1ENR.word |= apb1_mask & APB1_MASK;
|
||||
regs->APB2ENR.word |= apb2_mask & APB2_MASK;
|
||||
}
|
||||
|
||||
void rcc_disable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
|
||||
enum RccApb2 apb2_mask)
|
||||
{
|
||||
regs->AHBENR.word &= !(ahb_mask & AHB_MASK);
|
||||
regs->APB1ENR.word &= !(apb1_mask & APB1_MASK);
|
||||
regs->APB2ENR.word &= !(apb2_mask & APB2_MASK);
|
||||
}
|
||||
|
||||
void rcc_reset(enum RccApb1 apb1_mask, enum RccApb2 apb2_mask)
|
||||
{
|
||||
regs->APB1RSTR.word &= !(apb1_mask & APB1_MASK);
|
||||
regs->APB2RSTR.word &= !(apb2_mask & APB2_MASK);
|
||||
}
|
||||
|
||||
void rcc_get_clocks(struct RccClocks* clocks)
|
||||
{
|
||||
switch (current_preset)
|
||||
{
|
||||
case RCC_PRESET_DEFAULT:
|
||||
clocks->ahb_freq = 8000000;
|
||||
clocks->apb1_freq = 8000000;
|
||||
clocks->apb2_freq = 8000000;
|
||||
break;
|
||||
case RCC_PRESET_SPEED:
|
||||
clocks->ahb_freq = 72000000;
|
||||
clocks->apb1_freq = 36000000;
|
||||
clocks->apb2_freq = 72000000;
|
||||
break;
|
||||
default:
|
||||
//TODO hardfault
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Apply the default clock preset, using HSI whithout PLL or prescalers. This is
|
||||
* similar to the reset configuration. Most buses run at 8Mhz, except ADCs wich
|
||||
* run at 4Mhz, and Systick wich only reaches 1Mhz.
|
||||
*/
|
||||
static void apply_default_preset(void)
|
||||
{
|
||||
//ensures HSI is enabled
|
||||
reg_set(regs->CR, RCC_CR_HSION);
|
||||
while (regs->CR.HSIRDY != 0x1);
|
||||
|
||||
//set HSI as main clock source and disable prescalers
|
||||
regs->CFGR.word &= ~0x077fff3;
|
||||
|
||||
//disable all options
|
||||
reg_reset(regs->CR, RCC_CR_HSITRIM);
|
||||
reg_write(regs->CR, RCC_CR_HSITRIM, 0x10);
|
||||
reg_reset(regs->CR, RCC_CR_HSEON);
|
||||
reg_reset(regs->CR, RCC_CR_HSEBYP);
|
||||
reg_reset(regs->CR, RCC_CR_CCSON);
|
||||
reg_reset(regs->CR, RCC_CR_PLLON);
|
||||
|
||||
//disable all interrupts
|
||||
reg_reset(regs->CIR, RCC_CIR_LSIRDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_LSERDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_HSIRDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_HSERDYIE);
|
||||
reg_reset(regs->CIR, RCC_CIR_PLLRDYIE);
|
||||
|
||||
//reconfigure flash
|
||||
flash_configure(FLASH_PRESET_LOW_CLOCK_SPEED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the speed preset, using HSE with PLL to achieve 72MHz on AHB, APB2 and
|
||||
* timer buses. APB1 is limited to its maximum clock of 36Mhz and the ADCs run
|
||||
* at 12MHz. Systick runs at 9Mhz.
|
||||
*/
|
||||
static void apply_speed_preset(void)
|
||||
{
|
||||
//restore sane values
|
||||
apply_default_preset();
|
||||
|
||||
//try enabling HSE, fallback to HSI if HSE fails
|
||||
reg_set(regs->CR, RCC_CR_HSEON);
|
||||
for (uint32_t i=0; i<1000; ++i) {
|
||||
__asm__("nop");
|
||||
}
|
||||
if (regs->CR.HSERDY == 0x1) {
|
||||
reg_set(regs->CFGR, RCC_CFGR_PLLSCR);
|
||||
} else {
|
||||
reg_reset(regs->CR, RCC_CR_HSEON);
|
||||
}
|
||||
|
||||
//configure PLL, fallback to HSI if PLL fails
|
||||
reg_write(regs->CFGR, RCC_CFGR_PLLMUL, 0x7); //PLL x9
|
||||
reg_set(regs->CR, RCC_CR_PLLON);
|
||||
for (uint32_t i=0; i<1000; ++i) {
|
||||
__asm__("nop");
|
||||
}
|
||||
if (regs->CR.PLLRDY != 0x1) {
|
||||
reg_reset(regs->CR, RCC_CR_PLLON);
|
||||
return; //clock low enough, no need for prescalers
|
||||
}
|
||||
|
||||
//configure prescalers
|
||||
reg_write(regs->CFGR, RCC_CFGR_PPRE1, 0x4); // /2
|
||||
reg_write(regs->CFGR, RCC_CFGR_ADCPRE, 0x2); // /6
|
||||
|
||||
//reconfigure flash
|
||||
flash_configure(FLASH_PRESET_HIGH_CLOCK_SPEED);
|
||||
|
||||
//switch to PLL output
|
||||
reg_write(regs->CFGR, RCC_CFGR_SW, 0x2);
|
||||
}
|
||||
|
||||
142
drv/rcc.h
Normal file
142
drv/rcc.h
Normal file
@ -0,0 +1,142 @@
|
||||
/** @file rcc.h
|
||||
* Module handling Reset and Clocks Control (RCC).
|
||||
*
|
||||
* The module provides functions to configure clocks according to presets as
|
||||
* well as to enable/disable/reset peripherals.
|
||||
*/
|
||||
|
||||
#ifndef _RCC_H_
|
||||
#define _RCC_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available clock configuration presets
|
||||
*/
|
||||
enum RccPreset {
|
||||
RCC_PRESET_DEFAULT, //sane values, identical to reset config
|
||||
RCC_PRESET_SPEED, //highest clocks, uses 8MHz HSE if available
|
||||
};
|
||||
|
||||
/**
|
||||
* Available peripherals on the AHB bus. Note that some of these peripherals
|
||||
* may not be availables on all chips
|
||||
*/
|
||||
enum RccAhb {
|
||||
RCC_AHB_NONE = 0,
|
||||
RCC_AHB_DMA1 = (0x1 << 0),
|
||||
RCC_AHB_DMA2 = (0x1 << 1),
|
||||
RCC_AHB_SRAM = (0x1 << 2),
|
||||
RCC_AHB_FLITF = (0x1 << 4),
|
||||
RCC_AHB_CRC = (0x1 << 6),
|
||||
RCC_AHB_FSMC = (0x1 << 8),
|
||||
RCC_AHB_SDIO = (0x1 << 10),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available peripherals on the APB1 bus. Note that some of these peripherals
|
||||
* may not be availables on all chips
|
||||
*/
|
||||
enum RccApb1 {
|
||||
RCC_APB1_NONE = 0,
|
||||
RCC_APB1_TIM2 = (0x1 << 0),
|
||||
RCC_APB1_TIM3 = (0x1 << 1),
|
||||
RCC_APB1_TIM4 = (0x1 << 2),
|
||||
RCC_APB1_TIM5 = (0x1 << 3),
|
||||
RCC_APB1_TIM6 = (0x1 << 4),
|
||||
RCC_APB1_TIM7 = (0x1 << 5),
|
||||
RCC_APB1_TIM12 = (0x1 << 6),
|
||||
RCC_APB1_TIM13 = (0x1 << 7),
|
||||
RCC_APB1_TIM14 = (0x1 << 8),
|
||||
RCC_APB1_WWDG = (0x1 << 11),
|
||||
RCC_APB1_SPI2 = (0x1 << 14),
|
||||
RCC_APB1_SPI3 = (0x1 << 15),
|
||||
RCC_APB1_USART2 = (0x1 << 17),
|
||||
RCC_APB1_USART3 = (0x1 << 18),
|
||||
RCC_APB1_UART4 = (0x1 << 19),
|
||||
RCC_APB1_UART5 = (0x1 << 20),
|
||||
RCC_APB1_I2C1 = (0x1 << 21),
|
||||
RCC_APB1_I2C2 = (0x1 << 22),
|
||||
RCC_APB1_USB = (0x1 << 23),
|
||||
RCC_APB1_CAN = (0x1 << 25),
|
||||
RCC_APB1_BKP = (0x1 << 27),
|
||||
RCC_APB1_PWR = (0x1 << 28),
|
||||
RCC_APB1_DAC = (0x1 << 29),
|
||||
};
|
||||
|
||||
/**
|
||||
* Available peripherals on the APB2 bus. Note that some of these peripherals
|
||||
* may not be available on all chips
|
||||
*/
|
||||
enum RccApb2 {
|
||||
RCC_APB2_NONE = 0,
|
||||
RCC_APB2_AFIO = (0x1 << 0),
|
||||
RCC_APB2_IOPA = (0x1 << 2),
|
||||
RCC_APB2_IOPB = (0x1 << 3),
|
||||
RCC_APB2_IOPC = (0x1 << 4),
|
||||
RCC_APB2_IOPD = (0x1 << 5),
|
||||
RCC_APB2_IOPE = (0x1 << 6),
|
||||
RCC_APB2_IOPF = (0x1 << 7),
|
||||
RCC_APB2_IOPG = (0x1 << 8),
|
||||
RCC_APB2_ADC1 = (0x1 << 9),
|
||||
RCC_APB2_ADC2 = (0x1 << 10),
|
||||
RCC_APB2_TIM1 = (0x1 << 11),
|
||||
RCC_APB2_SPI1 = (0x1 << 12),
|
||||
RCC_APB2_TIM8 = (0x1 << 13),
|
||||
RCC_APB2_USART = (0x1 << 14),
|
||||
RCC_APB2_ADC3 = (0x1 << 15),
|
||||
RCC_APB2_TIM9 = (0x1 << 19),
|
||||
RCC_APB2_TIM10 = (0x1 << 20),
|
||||
RCC_APB2_TIM11 = (0x1 << 21),
|
||||
};
|
||||
|
||||
struct RccClocks {
|
||||
uint32_t ahb_freq;
|
||||
uint32_t apb1_freq;
|
||||
uint32_t apb2_freq;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the clocks and buses according to the given preset. Peripheral
|
||||
* states are kept during the change and additional reconfiguration are
|
||||
* handled automatically for peripherals that rely on a clock timings (timers,
|
||||
* watchdogs, ...)
|
||||
*/
|
||||
void rcc_configure(enum RccPreset preset);
|
||||
|
||||
/**
|
||||
* Enables peripherals on the different buses. The enums values can used as
|
||||
* masks to enable multiple peripherals at the same time. Invalid values will be
|
||||
* ignored.
|
||||
*/
|
||||
void rcc_enable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
|
||||
enum RccApb2 apb2_mask);
|
||||
|
||||
/**
|
||||
* Disables peripherals on the different buses. The enums values can used as
|
||||
* masks to disable multiple peripherals at the same time. Invalid values will
|
||||
* be ignored.
|
||||
*/
|
||||
void rcc_disable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
|
||||
enum RccApb2 apb2_mask);
|
||||
|
||||
/**
|
||||
* Resets peripherals on the different buses. The enums values can used as
|
||||
* masks to reset multiple peripherals at the same time. Invalid values will
|
||||
* be ignored.
|
||||
*/
|
||||
void rcc_reset(enum RccApb1 apb1_mask, enum RccApb2 apb2_mask);
|
||||
|
||||
void rcc_get_clocks(struct RccClocks* clocks);
|
||||
|
||||
|
||||
#endif //_RCC_H_
|
||||
|
||||
468
drv/rcc_regs.h
Normal file
468
drv/rcc_regs.h
Normal file
@ -0,0 +1,468 @@
|
||||
/** @file rcc_regs.h
|
||||
* Module defining Reset and Clocks Control (RCC) registers.
|
||||
*
|
||||
* Mainly made to be used by the rcc module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _RCC_REGS_H_
|
||||
#define _RCC_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define RCC_BASE_ADDRESS 0x40021000
|
||||
|
||||
union RCC_CR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t HSION:1;
|
||||
uint32_t HSIRDY:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t HSITRIM:5;
|
||||
uint32_t HSICAL:8;
|
||||
uint32_t HSEON:1;
|
||||
uint32_t HSERDY:1;
|
||||
uint32_t HSEBYP:1;
|
||||
uint32_t CCSON:1;
|
||||
uint32_t reserved2:4;
|
||||
uint32_t PLLON:1;
|
||||
uint32_t PLLRDY:1;
|
||||
uint32_t reserved3:6;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CR_HSION reg_def( 0, 1)
|
||||
#define RCC_CR_HSIRDY reg_def( 1, 1)
|
||||
#define RCC_CR_reserved1 reg_def( 2, 1)
|
||||
#define RCC_CR_HSITRIM reg_def( 3, 5)
|
||||
#define RCC_CR_HSICAL reg_def( 8, 8)
|
||||
#define RCC_CR_HSEON reg_def(16, 1)
|
||||
#define RCC_CR_HSERDY reg_def(17, 1)
|
||||
#define RCC_CR_HSEBYP reg_def(18, 1)
|
||||
#define RCC_CR_CCSON reg_def(19, 1)
|
||||
#define RCC_CR_reserved2 reg_def(20, 4)
|
||||
#define RCC_CR_PLLON reg_def(24, 1)
|
||||
#define RCC_CR_PLLRDY reg_def(25, 1)
|
||||
#define RCC_CR_reserved3 reg_def(26, 6)
|
||||
|
||||
union RCC_CFGR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t SW:2;
|
||||
uint32_t SWS:2;
|
||||
uint32_t HPRE:4;
|
||||
uint32_t PPRE1:3;
|
||||
uint32_t PPRE2:3;
|
||||
uint32_t ADCPRE:2;
|
||||
uint32_t PLLSCR:1;
|
||||
uint32_t PLLXTPRE:1;
|
||||
uint32_t PLLMUL:4;
|
||||
uint32_t USBPRE:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t MCO:3;
|
||||
uint32_t reserved2:5;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CFGR_SW reg_def( 0, 2)
|
||||
#define RCC_CFGR_SWS reg_def( 2, 2)
|
||||
#define RCC_CFGR_HPRE reg_def( 4, 4)
|
||||
#define RCC_CFGR_PPRE1 reg_def( 8, 3)
|
||||
#define RCC_CFGR_PPRE2 reg_def(11, 3)
|
||||
#define RCC_CFGR_ADCPRE reg_def(14, 2)
|
||||
#define RCC_CFGR_PLLSCR reg_def(16, 1)
|
||||
#define RCC_CFGR_PLLXTPRE reg_def(17, 1)
|
||||
#define RCC_CFGR_PLLMUL reg_def(18, 4)
|
||||
#define RCC_CFGR_USBPRE reg_def(22, 1)
|
||||
#define RCC_CFGR_reserved1 reg_def(23, 1)
|
||||
#define RCC_CFGR_MCO reg_def(24, 3)
|
||||
#define RCC_CFGR_reserved2 reg_def(27, 5)
|
||||
|
||||
union RCC_CIR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t LSIRDYF:1;
|
||||
uint32_t LSERDYF:1;
|
||||
uint32_t HSIRDYF:1;
|
||||
uint32_t HSERDYF:1;
|
||||
uint32_t PLLRDYF:1;
|
||||
uint32_t reserved1:2;
|
||||
uint32_t CSSF:1;
|
||||
uint32_t LSIRDYIE:1;
|
||||
uint32_t LSERDYIE:1;
|
||||
uint32_t HSIRDYIE:1;
|
||||
uint32_t HSERDYIE:1;
|
||||
uint32_t PLLRDYIE:1;
|
||||
uint32_t RSE2:3;
|
||||
uint32_t LSIRDYC:1;
|
||||
uint32_t LSERDYC:1;
|
||||
uint32_t HSIRDYC:1;
|
||||
uint32_t HSERDYC:1;
|
||||
uint32_t PLLRDYC:1;
|
||||
uint32_t reserved3:2;
|
||||
uint32_t CSSC:1;
|
||||
uint32_t reserved4:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CIR_LSIRDYF reg_def( 0, 1)
|
||||
#define RCC_CIR_LSERDYF reg_def( 1, 1)
|
||||
#define RCC_CIR_HSIRDYF reg_def( 2, 1)
|
||||
#define RCC_CIR_HSERDYF reg_def( 3, 1)
|
||||
#define RCC_CIR_PLLRDYF reg_def( 4, 1)
|
||||
#define RCC_CIR_reserved1 reg_def( 5, 2)
|
||||
#define RCC_CIR_CSSF reg_def( 7, 1)
|
||||
#define RCC_CIR_LSIRDYIE reg_def( 8, 1)
|
||||
#define RCC_CIR_LSERDYIE reg_def( 9, 1)
|
||||
#define RCC_CIR_HSIRDYIE reg_def(10, 1)
|
||||
#define RCC_CIR_HSERDYIE reg_def(11, 1)
|
||||
#define RCC_CIR_PLLRDYIE reg_def(12, 1)
|
||||
#define RCC_CIR_RSE2 reg_def(13, 3)
|
||||
#define RCC_CIR_LSIRDYC reg_def(16, 1)
|
||||
#define RCC_CIR_LSERDYC reg_def(17, 1)
|
||||
#define RCC_CIR_HSIRDYC reg_def(18, 1)
|
||||
#define RCC_CIR_HSERDYC reg_def(19, 1)
|
||||
#define RCC_CIR_PLLRDYC reg_def(20, 1)
|
||||
#define RCC_CIR_reserved3 reg_def(21, 2)
|
||||
#define RCC_CIR_CSSC reg_def(23, 1)
|
||||
#define RCC_CIR_reserved4 reg_def(24, 8)
|
||||
|
||||
union RCC_APB2RSTR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t AFIORST:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t IOPARST:1;
|
||||
uint32_t IOPBRST:1;
|
||||
uint32_t IOPCRST:1;
|
||||
uint32_t IOPDRST:1;
|
||||
uint32_t IOPERST:1;
|
||||
uint32_t IOPFRST:1;
|
||||
uint32_t IOPGRST:1;
|
||||
uint32_t ADC1RST:1;
|
||||
uint32_t ACD2RST:1;
|
||||
uint32_t TIM1RST:1;
|
||||
uint32_t SPI1RST:1;
|
||||
uint32_t TIM8RST:1;
|
||||
uint32_t USART1RST:1;
|
||||
uint32_t ADC3RST:1;
|
||||
uint32_t reserved2:3;
|
||||
uint32_t TIM9RST:1;
|
||||
uint32_t TIM10RST:1;
|
||||
uint32_t TIM11RST:1;
|
||||
uint32_t reserved3:10;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB2RSTR_AFIORST reg_def( 0, 1)
|
||||
#define RCC_APB2RSTR_reserved1 reg_def( 1, 1)
|
||||
#define RCC_APB2RSTR_IOPARST reg_def( 2, 1)
|
||||
#define RCC_APB2RSTR_IOPBRST reg_def( 3, 1)
|
||||
#define RCC_APB2RSTR_IOPCRST reg_def( 4, 1)
|
||||
#define RCC_APB2RSTR_IOPDRST reg_def( 5, 1)
|
||||
#define RCC_APB2RSTR_IOPERST reg_def( 6, 1)
|
||||
#define RCC_APB2RSTR_IOPFRST reg_def( 7, 1)
|
||||
#define RCC_APB2RSTR_IOPGRST reg_def( 8, 1)
|
||||
#define RCC_APB2RSTR_ADC1RST reg_def( 9, 1)
|
||||
#define RCC_APB2RSTR_ACD2RST reg_def(10, 1)
|
||||
#define RCC_APB2RSTR_TIM1RST reg_def(11, 1)
|
||||
#define RCC_APB2RSTR_SPI1RST reg_def(12, 1)
|
||||
#define RCC_APB2RSTR_TIM8RST reg_def(13, 1)
|
||||
#define RCC_APB2RSTR_USART1RST reg_def(14, 1)
|
||||
#define RCC_APB2RSTR_ADC3RST reg_def(15, 1)
|
||||
#define RCC_APB2RSTR_reserved2 reg_def(16, 3)
|
||||
#define RCC_APB2RSTR_TIM9RST reg_def(19, 1)
|
||||
#define RCC_APB2RSTR_TIM10RST reg_def(20, 1)
|
||||
#define RCC_APB2RSTR_TIM11RST reg_def(21, 1)
|
||||
#define RCC_APB2RSTR_reserved3 reg_def(22, 10)
|
||||
|
||||
union RCC_APB1RSTR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t TIM2RST:1;
|
||||
uint32_t TIM3RST:1;
|
||||
uint32_t TIM4RST:1;
|
||||
uint32_t TIM5RST:1;
|
||||
uint32_t TIM6RST:1;
|
||||
uint32_t TIM7RST:1;
|
||||
uint32_t TIM12RST:1;
|
||||
uint32_t TIM13RST:1;
|
||||
uint32_t TIM14RST:1;
|
||||
uint32_t reserved1:2;
|
||||
uint32_t WWDGRST:1;
|
||||
uint32_t reserved2:2;
|
||||
uint32_t SPI2RST:1;
|
||||
uint32_t SPI3RST:1;
|
||||
uint32_t reserved3:1;
|
||||
uint32_t USART2RST:1;
|
||||
uint32_t USART3RST:1;
|
||||
uint32_t UART4RST:1;
|
||||
uint32_t UART5RST:1;
|
||||
uint32_t I2C12RST:1;
|
||||
uint32_t I2C2RST:1;
|
||||
uint32_t USB2RST:1;
|
||||
uint32_t reserved4:1;
|
||||
uint32_t CANRST:1;
|
||||
uint32_t reserved5:1;
|
||||
uint32_t BKPRST:1;
|
||||
uint32_t PWRRST:1;
|
||||
uint32_t DACRST:1;
|
||||
uint32_t reserved6:2;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB1RSTR_TIM2RST reg_def( 0, 1)
|
||||
#define RCC_APB1RSTR_TIM3RST reg_def( 1, 1)
|
||||
#define RCC_APB1RSTR_TIM4RST reg_def( 2, 1)
|
||||
#define RCC_APB1RSTR_TIM5RST reg_def( 3, 1)
|
||||
#define RCC_APB1RSTR_TIM6RST reg_def( 4, 1)
|
||||
#define RCC_APB1RSTR_TIM7RST reg_def( 5, 1)
|
||||
#define RCC_APB1RSTR_TIM12RST reg_def( 6, 1)
|
||||
#define RCC_APB1RSTR_TIM13RST reg_def( 7, 1)
|
||||
#define RCC_APB1RSTR_TIM14RST reg_def( 8, 1)
|
||||
#define RCC_APB1RSTR_reserved1 reg_def( 9, 2)
|
||||
#define RCC_APB1RSTR_WWDGRST reg_def(11, 1)
|
||||
#define RCC_APB1RSTR_reserved2 reg_def(12, 2)
|
||||
#define RCC_APB1RSTR_SPI2RST reg_def(14, 1)
|
||||
#define RCC_APB1RSTR_SPI3RST reg_def(15, 1)
|
||||
#define RCC_APB1RSTR_reserved3 reg_def(16, 1)
|
||||
#define RCC_APB1RSTR_USART2RST reg_def(17, 1)
|
||||
#define RCC_APB1RSTR_USART3RST reg_def(18, 1)
|
||||
#define RCC_APB1RSTR_UART4RST reg_def(19, 1)
|
||||
#define RCC_APB1RSTR_UART5RST reg_def(20, 1)
|
||||
#define RCC_APB1RSTR_I2C12RST reg_def(21, 1)
|
||||
#define RCC_APB1RSTR_I2C2RST reg_def(22, 1)
|
||||
#define RCC_APB1RSTR_USB2RST reg_def(23, 1)
|
||||
#define RCC_APB1RSTR_reserved4 reg_def(24, 1)
|
||||
#define RCC_APB1RSTR_CANRST reg_def(25, 1)
|
||||
#define RCC_APB1RSTR_reserved5 reg_def(26, 1)
|
||||
#define RCC_APB1RSTR_BKPRST reg_def(27, 1)
|
||||
#define RCC_APB1RSTR_PWRRST reg_def(28, 1)
|
||||
#define RCC_APB1RSTR_DACRST reg_def(29, 1)
|
||||
#define RCC_APB1RSTR_reserved6 reg_def(30, 2)
|
||||
|
||||
union RCC_AHBENR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t DMA1EN:1;
|
||||
uint32_t DMA2EN:1;
|
||||
uint32_t SRAMEN:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t FLITFEN:1;
|
||||
uint32_t reserved2:1;
|
||||
uint32_t CRCEN:1;
|
||||
uint32_t reserved3:1;
|
||||
uint32_t FSMCEN:1;
|
||||
uint32_t reserved4:1;
|
||||
uint32_t SDIOEN:1;
|
||||
uint32_t reserved5:21;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_AHBENR_DMA1EN reg_def( 0, 1)
|
||||
#define RCC_AHBENR_DMA2EN reg_def( 1, 1)
|
||||
#define RCC_AHBENR_SRAMEN reg_def( 2, 1)
|
||||
#define RCC_AHBENR_reserved1 reg_def( 3, 1)
|
||||
#define RCC_AHBENR_FLITFEN reg_def( 4, 1)
|
||||
#define RCC_AHBENR_reserved2 reg_def( 5, 1)
|
||||
#define RCC_AHBENR_CRCEN reg_def( 6, 1)
|
||||
#define RCC_AHBENR_reserved3 reg_def( 7, 1)
|
||||
#define RCC_AHBENR_FSMCEN reg_def( 8, 1)
|
||||
#define RCC_AHBENR_reserved4 reg_def( 9, 1)
|
||||
#define RCC_AHBENR_SDIOEN reg_def(10, 1)
|
||||
#define RCC_AHBENR_reserved5 reg_def(11, 21)
|
||||
|
||||
union RCC_APB2ENR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t AFIOEN:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t IOPAEN:1;
|
||||
uint32_t IOPBEN:1;
|
||||
uint32_t IOPCEN:1;
|
||||
uint32_t IOPDEN:1;
|
||||
uint32_t IOPEEN:1;
|
||||
uint32_t IOPFEN:1;
|
||||
uint32_t IOPGEN:1;
|
||||
uint32_t ADC1EN:1;
|
||||
uint32_t ACD2EN:1;
|
||||
uint32_t TIM1EN:1;
|
||||
uint32_t SPI1EN:1;
|
||||
uint32_t TIM8EN:1;
|
||||
uint32_t USART1EN:1;
|
||||
uint32_t ADC3EN:1;
|
||||
uint32_t reserved2:3;
|
||||
uint32_t TIM9EN:1;
|
||||
uint32_t TIM10EN:1;
|
||||
uint32_t TIM11EN:1;
|
||||
uint32_t reserved3:10;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB2ENR_AFIOEN reg_def( 0, 1)
|
||||
#define RCC_APB2ENR_reserved1 reg_def( 1, 1)
|
||||
#define RCC_APB2ENR_IOPAEN reg_def( 2, 1)
|
||||
#define RCC_APB2ENR_IOPBEN reg_def( 3, 1)
|
||||
#define RCC_APB2ENR_IOPCEN reg_def( 4, 1)
|
||||
#define RCC_APB2ENR_IOPDEN reg_def( 5, 1)
|
||||
#define RCC_APB2ENR_IOPEEN reg_def( 6, 1)
|
||||
#define RCC_APB2ENR_IOPFEN reg_def( 7, 1)
|
||||
#define RCC_APB2ENR_IOPGEN reg_def( 8, 1)
|
||||
#define RCC_APB2ENR_ADC1EN reg_def( 9, 1)
|
||||
#define RCC_APB2ENR_ACD2EN reg_def(10, 1)
|
||||
#define RCC_APB2ENR_TIM1EN reg_def(11, 1)
|
||||
#define RCC_APB2ENR_SPI1EN reg_def(12, 1)
|
||||
#define RCC_APB2ENR_TIM8EN reg_def(13, 1)
|
||||
#define RCC_APB2ENR_USART1EN reg_def(14, 1)
|
||||
#define RCC_APB2ENR_ADC3EN reg_def(15, 1)
|
||||
#define RCC_APB2ENR_reserved2 reg_def(16, 3)
|
||||
#define RCC_APB2ENR_TIM9EN reg_def(19, 1)
|
||||
#define RCC_APB2ENR_TIM10EN reg_def(20, 1)
|
||||
#define RCC_APB2ENR_TIM11EN reg_def(21, 1)
|
||||
#define RCC_APB2ENR_reserved3 reg_def(22, 10)
|
||||
|
||||
union RCC_APB1ENR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t TIM2EN:1;
|
||||
uint32_t TIM3EN:1;
|
||||
uint32_t TIM4EN:1;
|
||||
uint32_t TIM5EN:1;
|
||||
uint32_t TIM6EN:1;
|
||||
uint32_t TIM7EN:1;
|
||||
uint32_t TIM12EN:1;
|
||||
uint32_t TIM13EN:1;
|
||||
uint32_t TIM14EN:1;
|
||||
uint32_t reserved1:2;
|
||||
uint32_t WWDGEN:1;
|
||||
uint32_t reserved2:2;
|
||||
uint32_t SPI2EN:1;
|
||||
uint32_t SPI3EN:1;
|
||||
uint32_t reserved3:1;
|
||||
uint32_t USART2EN:1;
|
||||
uint32_t USART3EN:1;
|
||||
uint32_t UART4EN:1;
|
||||
uint32_t UART5EN:1;
|
||||
uint32_t I2C12EN:1;
|
||||
uint32_t I2C2EN:1;
|
||||
uint32_t USB2EN:1;
|
||||
uint32_t reserved4:1;
|
||||
uint32_t CANEN:1;
|
||||
uint32_t reserved5:1;
|
||||
uint32_t BKPEN:1;
|
||||
uint32_t PWREN:1;
|
||||
uint32_t DACEN:1;
|
||||
uint32_t reserved6:2;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_APB1ENR_TIM2EN reg_def( 0, 1)
|
||||
#define RCC_APB1ENR_TIM3EN reg_def( 1, 1)
|
||||
#define RCC_APB1ENR_TIM4EN reg_def( 2, 1)
|
||||
#define RCC_APB1ENR_TIM5EN reg_def( 3, 1)
|
||||
#define RCC_APB1ENR_TIM6EN reg_def( 4, 1)
|
||||
#define RCC_APB1ENR_TIM7EN reg_def( 5, 1)
|
||||
#define RCC_APB1ENR_TIM12EN reg_def( 6, 1)
|
||||
#define RCC_APB1ENR_TIM13EN reg_def( 7, 1)
|
||||
#define RCC_APB1ENR_TIM14EN reg_def( 8, 1)
|
||||
#define RCC_APB1ENR_reserved1 reg_def( 9, 2)
|
||||
#define RCC_APB1ENR_WWDGEN reg_def(11, 1)
|
||||
#define RCC_APB1ENR_reserved reg_def(12, 2)
|
||||
#define RCC_APB1ENR_SPI2EN reg_def(14, 1)
|
||||
#define RCC_APB1ENR_SPI3EN reg_def(15, 1)
|
||||
#define RCC_APB1ENR_reserved2 reg_def(16, 1)
|
||||
#define RCC_APB1ENR_USART2EN reg_def(17, 1)
|
||||
#define RCC_APB1ENR_USART3EN reg_def(18, 1)
|
||||
#define RCC_APB1ENR_UART4EN reg_def(19, 1)
|
||||
#define RCC_APB1ENR_UART5EN reg_def(20, 1)
|
||||
#define RCC_APB1ENR_I2C12EN reg_def(21, 1)
|
||||
#define RCC_APB1ENR_I2C2EN reg_def(22, 1)
|
||||
#define RCC_APB1ENR_USB2EN reg_def(23, 1)
|
||||
#define RCC_APB1ENR_reserved3 reg_def(24, 1)
|
||||
#define RCC_APB1ENR_CANEN reg_def(25, 1)
|
||||
#define RCC_APB1ENR_reserved4 reg_def(26, 1)
|
||||
#define RCC_APB1ENR_BKPEN reg_def(27, 1)
|
||||
#define RCC_APB1ENR_PWREN reg_def(28, 1)
|
||||
#define RCC_APB1ENR_DACEN reg_def(29, 1)
|
||||
#define RCC_APB1ENR_reserved5 reg_def(30, 2)
|
||||
|
||||
union RCC_BDCR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t LSEON:1;
|
||||
uint32_t LSERDY:1;
|
||||
uint32_t LSEBYP:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t RTCSEL:2;
|
||||
uint32_t reserved2:5;
|
||||
uint32_t RTCEN:1;
|
||||
uint32_t BDRST:1;
|
||||
uint32_t reserved3:15;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_BDCR_LSEON reg_def( 0, 1)
|
||||
#define RCC_BDCR_LSERDY reg_def( 1, 1)
|
||||
#define RCC_BDCR_LSEBYP reg_def( 2, 1)
|
||||
#define RCC_BDCR_reserved1 reg_def( 3, 5)
|
||||
#define RCC_BDCR_RTCSEL reg_def( 8, 2)
|
||||
#define RCC_BDCR_reserved2 reg_def(10, 5)
|
||||
#define RCC_BDCR_RTCEN reg_def(15, 1)
|
||||
#define RCC_BDCR_BDRST reg_def(16, 1)
|
||||
#define RCC_BDCR_reserved3 reg_def(17, 15)
|
||||
|
||||
union RCC_CSR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t LSION:1;
|
||||
uint32_t LSIRDY:1;
|
||||
uint32_t reserved1:22;
|
||||
uint32_t RMVF:1;
|
||||
uint32_t reserved2:1;
|
||||
uint32_t PINRSTF:1;
|
||||
uint32_t PORRSTF:1;
|
||||
uint32_t SFTRSTF:1;
|
||||
uint32_t IWDGRSTF:1;
|
||||
uint32_t WWDGRSTF:1;
|
||||
uint32_t LPWRSTF:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define RCC_CSR_LSION reg_def( 0, 1)
|
||||
#define RCC_CSR_LSIRDY reg_def( 1, 1)
|
||||
#define RCC_CSR_reserved1 reg_def( 2, 22)
|
||||
#define RCC_CSR_RMVF reg_def(24, 1)
|
||||
#define RCC_CSR_reserved2 reg_def(25, 1)
|
||||
#define RCC_CSR_PINRSTF reg_def(26, 1)
|
||||
#define RCC_CSR_PORRSTF reg_def(27, 1)
|
||||
#define RCC_CSR_SFTRSTF reg_def(28, 1)
|
||||
#define RCC_CSR_IWDGRSTF reg_def(29, 1)
|
||||
#define RCC_CSR_WWDGRSTF reg_def(30, 1)
|
||||
#define RCC_CSR_LPWRSTF reg_def(31, 1)
|
||||
|
||||
struct __attribute__((packed)) RCC {
|
||||
union RCC_CR CR;
|
||||
union RCC_CFGR CFGR;
|
||||
union RCC_CIR CIR;
|
||||
union RCC_APB2RSTR APB2RSTR;
|
||||
union RCC_APB1RSTR APB1RSTR;
|
||||
union RCC_AHBENR AHBENR;
|
||||
union RCC_APB2ENR APB2ENR;
|
||||
union RCC_APB1ENR APB1ENR;
|
||||
union RCC_BDCR BDCR;
|
||||
union RCC_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_RCC_REGS_H_
|
||||
|
||||
15
drv/reg.h
Normal file
15
drv/reg.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#define reg_def(pos, size) pos, (((0x1 << size) - 1) << pos)
|
||||
|
||||
#define reg_set(reg, field) _reg_set(reg, field)
|
||||
#define _reg_set(reg, pos, mask) do { reg.word |= mask; } while (false)
|
||||
|
||||
#define reg_reset(reg, field) _reg_reset(reg, field)
|
||||
#define _reg_reset(reg, pos, mask) do { reg.word &= ~mask; } while (false)
|
||||
|
||||
#define reg_write(reg, field, value) _reg_write(reg, field, (value))
|
||||
#define _reg_write(reg, pos, mask, value) \
|
||||
do { \
|
||||
reg.word |= value << pos; \
|
||||
} while (false) \
|
||||
|
||||
263
drv/usart.c
Normal file
263
drv/usart.c
Normal file
@ -0,0 +1,263 @@
|
||||
/** @file usart.c
|
||||
* Module handling Universal Synchronous/Asynchronous Receiver/Transmitter
|
||||
*
|
||||
* The module provides functions to configure the usarts and read/write from/to
|
||||
* it
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "usart.h"
|
||||
#include "usart_regs.h"
|
||||
#include "reg.h"
|
||||
|
||||
#include "rcc.h"
|
||||
#include "dma.h"
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static void configure_usart(volatile struct USART* regs,
|
||||
enum UsartConfig config);
|
||||
static void configure_baudrate(volatile struct USART* regs, uint32_t clock,
|
||||
uint32_t baudrate);
|
||||
|
||||
#define DMA_CONFIG (DMA_CONFIG_PSIZE_8BITS)
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct USART* const usarts[] = {
|
||||
(struct USART*)USART1_BASE_ADDRESS,
|
||||
(struct USART*)USART2_BASE_ADDRESS,
|
||||
(struct USART*)USART3_BASE_ADDRESS,
|
||||
};
|
||||
|
||||
static const struct DmaParam usarts_rx_param[] = {
|
||||
{
|
||||
(void*)&usarts[USART_PERIPH_1]->DR,
|
||||
DMA_CONFIG,
|
||||
DMA_PERIPH_1,
|
||||
DMA_CHANNEL_5,
|
||||
},
|
||||
{
|
||||
(void*)&usarts[USART_PERIPH_2]->DR,
|
||||
DMA_CONFIG,
|
||||
DMA_PERIPH_1,
|
||||
DMA_CHANNEL_6,
|
||||
},
|
||||
{
|
||||
(void*)&usarts[USART_PERIPH_3]->DR,
|
||||
DMA_CONFIG,
|
||||
DMA_PERIPH_1,
|
||||
DMA_CHANNEL_3,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct DmaParam usarts_tx_param[] = {
|
||||
{
|
||||
(void*)&usarts[USART_PERIPH_1]->DR,
|
||||
DMA_CONFIG,
|
||||
DMA_PERIPH_1,
|
||||
DMA_CHANNEL_4,
|
||||
},
|
||||
{
|
||||
(void*)&usarts[USART_PERIPH_2]->DR,
|
||||
DMA_CONFIG,
|
||||
DMA_PERIPH_1,
|
||||
DMA_CHANNEL_7,
|
||||
},
|
||||
{
|
||||
(void*)&usarts[USART_PERIPH_3]->DR,
|
||||
DMA_CONFIG,
|
||||
DMA_PERIPH_1,
|
||||
DMA_CHANNEL_2,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void usart_configure(enum UsartPeriph periph, enum UsartConfig config,
|
||||
uint32_t baudrate)
|
||||
{
|
||||
struct RccClocks clocks;
|
||||
rcc_get_clocks(&clocks);
|
||||
|
||||
switch (periph) {
|
||||
case USART_PERIPH_1:
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_NONE, RCC_APB2_USART);
|
||||
configure_baudrate(usarts[USART_PERIPH_1], clocks.apb2_freq,
|
||||
baudrate);
|
||||
configure_usart(usarts[USART_PERIPH_1], config);
|
||||
break;
|
||||
case USART_PERIPH_2:
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_USART2, RCC_APB2_NONE);
|
||||
configure_baudrate(usarts[USART_PERIPH_2], clocks.apb1_freq,
|
||||
baudrate);
|
||||
configure_usart(usarts[USART_PERIPH_2], config);
|
||||
break;
|
||||
case USART_PERIPH_3:
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_USART3, RCC_APB2_NONE);
|
||||
configure_baudrate(usarts[USART_PERIPH_3], clocks.apb1_freq,
|
||||
baudrate);
|
||||
configure_usart(usarts[USART_PERIPH_3], config);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t usart_read_byte(enum UsartPeriph periph, uint8_t* byte)
|
||||
{
|
||||
if (periph > USART_PERIPH_3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (usarts[periph]->SR.RXNE) {
|
||||
*byte = usarts[periph]->DR.DR;
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t usart_write_byte(enum UsartPeriph periph, uint8_t byte)
|
||||
{
|
||||
if (periph > USART_PERIPH_3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//only write data if the tx register it empty, give up otherwise
|
||||
if (usarts[periph]->SR.TXE) {
|
||||
reg_write(usarts[periph]->DR, USART_DR_DR, byte);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const struct DmaParam* usart_configure_rx_dma(enum UsartPeriph periph)
|
||||
{
|
||||
if (periph > USART_PERIPH_3) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
reg_set(usarts[periph]->CR3, USART_CR3_DMAR);
|
||||
return &usarts_rx_param[periph];
|
||||
}
|
||||
|
||||
const struct DmaParam* usart_configure_tx_dma(enum UsartPeriph periph)
|
||||
{
|
||||
if (periph > USART_PERIPH_3) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
reg_set(usarts[periph]->CR3, USART_CR3_DMAT);
|
||||
return &usarts_tx_param[periph];
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Apply the given configuration to the given registers. Generic version of
|
||||
* usart_configure()
|
||||
*/
|
||||
static void configure_usart(volatile struct USART* regs,
|
||||
enum UsartConfig config)
|
||||
{
|
||||
//configure parity
|
||||
switch (config)
|
||||
{
|
||||
case USART_CONFIG_7E1:
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_7E2:
|
||||
case USART_CONFIG_8E2:
|
||||
reg_set(regs->CR1, USART_CR1_PCE);
|
||||
reg_reset(regs->CR1, USART_CR1_PS);
|
||||
break;
|
||||
case USART_CONFIG_7O1:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8O1:
|
||||
case USART_CONFIG_8O2:
|
||||
reg_set(regs->CR1, USART_CR1_PCE);
|
||||
reg_set(regs->CR1, USART_CR1_PS);
|
||||
break;
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8N2:
|
||||
reg_reset(regs->CR1, USART_CR1_PCE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//configure bit number
|
||||
switch (config)
|
||||
{
|
||||
case USART_CONFIG_7E1:
|
||||
case USART_CONFIG_7E2:
|
||||
case USART_CONFIG_7O1:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8N2:
|
||||
reg_reset(regs->CR1, USART_CR1_M);
|
||||
break;
|
||||
case USART_CONFIG_8E2:
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_8O1:
|
||||
case USART_CONFIG_8O2:
|
||||
reg_set(regs->CR1, USART_CR1_M);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//configure stop bits
|
||||
switch (config)
|
||||
{
|
||||
case USART_CONFIG_7E1:
|
||||
case USART_CONFIG_7O1:
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_8O1:
|
||||
reg_reset(regs->CR2, USART_CR2_STOP);
|
||||
break;
|
||||
case USART_CONFIG_7E2:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8N2:
|
||||
case USART_CONFIG_8E2:
|
||||
case USART_CONFIG_8O2:
|
||||
reg_reset(regs->CR2, USART_CR2_STOP);
|
||||
reg_write(regs->CR2, USART_CR2_STOP, 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//enable Rx/Tx
|
||||
reg_set(regs->CR1, USART_CR1_TE);
|
||||
reg_set(regs->CR1, USART_CR1_RE);
|
||||
reg_set(regs->CR1, USART_CR1_UE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the given registers with the given baudrate. Baudrate is dependant
|
||||
* on the peripheral's clock and may not be exact due to precision errors (see
|
||||
* table 192 in documentation)
|
||||
*/
|
||||
static void configure_baudrate(volatile struct USART* regs, uint32_t clock,
|
||||
uint32_t baudrate)
|
||||
{
|
||||
uint32_t mantissa = clock / (baudrate * 16);
|
||||
uint32_t factor = clock / baudrate;
|
||||
volatile uint32_t divider = factor - (mantissa * 16);
|
||||
|
||||
reg_reset(regs->BRR, USART_BRR_DIV_Mantissa);
|
||||
reg_write(regs->BRR, USART_BRR_DIV_Mantissa, mantissa & 0xFFF);
|
||||
reg_reset(regs->BRR, USART_BRR_DIV_Fraction);
|
||||
reg_write(regs->BRR, USART_BRR_DIV_Fraction, divider & 0xF);
|
||||
}
|
||||
|
||||
111
drv/usart.h
Normal file
111
drv/usart.h
Normal file
@ -0,0 +1,111 @@
|
||||
/** @file usart.h
|
||||
* Module handling Universal Synchronous/Asynchronous Receiver/Transmitter
|
||||
*
|
||||
* The module provides functions to configure the usarts and read/write from/to
|
||||
* it
|
||||
*/
|
||||
|
||||
#ifndef _USART_H_
|
||||
#define _USART_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "dma.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available USART peripherals. Note that some of these peripherals may not be
|
||||
* available on all chips
|
||||
*/
|
||||
enum UsartPeriph {
|
||||
USART_PERIPH_1,
|
||||
USART_PERIPH_2,
|
||||
USART_PERIPH_3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Available configuration options
|
||||
*/
|
||||
enum UsartConfig {
|
||||
USART_CONFIG_7E1,
|
||||
USART_CONFIG_7E2,
|
||||
USART_CONFIG_7O1,
|
||||
USART_CONFIG_7O2,
|
||||
USART_CONFIG_8N1,
|
||||
USART_CONFIG_8N2,
|
||||
USART_CONFIG_8E1,
|
||||
USART_CONFIG_8E2,
|
||||
USART_CONFIG_8O1,
|
||||
USART_CONFIG_8O2,
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the given USART peripheral using the provided condiguration
|
||||
* options and baudrate. The baudrate may be any value supported by the
|
||||
* peripheral, though some may not be exact due to precision errors (see
|
||||
* table 192 in documentation). The baudrate is dependant on the peripheral's
|
||||
* clock and changes to the later after this function has been called will cause
|
||||
* the effective baudrate to change
|
||||
*
|
||||
* This function doesn't configure the required ports. This should be done using
|
||||
* the gpio driver:
|
||||
* - Tx port should be using GPIO_CONFIG_OUT_ALT_PUSH_PULL with
|
||||
* the appropriate output speed based on the baurate (see GpioMode)
|
||||
* - Rx port should be using GPIO_CONFIG_IN_FLOATING in input mode
|
||||
* Both ports do not need to be configured if not used (e.g. if only using Tx,
|
||||
* the Rx port can be left unconfigured)
|
||||
*/
|
||||
void usart_configure(enum UsartPeriph periph, enum UsartConfig config,
|
||||
uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* Resets the given USART peripheral, applying the default configuration and
|
||||
* disabling it
|
||||
*/
|
||||
void usart_reset(enum UsartPeriph periph);
|
||||
|
||||
/**
|
||||
* Reads a single byte to the given USART peripheral, returning 0 if
|
||||
* successfull, 1 otherwise.
|
||||
*
|
||||
* The Rx port must be configured for this function to ever return successfully
|
||||
*/
|
||||
uint32_t usart_read_byte(enum UsartPeriph periph, uint8_t* byte);
|
||||
|
||||
/**
|
||||
* Writes a single byte to the given USART peripheral, returning 0 if
|
||||
* successfull, 1 otherwise.
|
||||
*
|
||||
* The Tx port must be configured for this function to do anything, though the
|
||||
* function would still return 0
|
||||
*/
|
||||
uint32_t usart_write_byte(enum UsartPeriph periph, uint8_t byte);
|
||||
|
||||
/**
|
||||
* Configures the given USART peripheral for DMA Rx operations, returning the
|
||||
* corresponding DMA parameters to be used.
|
||||
*
|
||||
* The DMA must be configured separately using the DMA driver or an existing
|
||||
* service
|
||||
*/
|
||||
const struct DmaParam* usart_configure_rx_dma(enum UsartPeriph periph);
|
||||
|
||||
/**
|
||||
* Configures the given USART peripheral for DMA Rx operations, returning the
|
||||
* corresponding DMA parameters to be used.
|
||||
*
|
||||
* The DMA must be configured separately using the DMA driver or an existing
|
||||
* service
|
||||
*/
|
||||
const struct DmaParam* usart_configure_tx_dma(enum UsartPeriph periph);
|
||||
|
||||
|
||||
#endif //_USART_H_
|
||||
|
||||
204
drv/usart_regs.h
Normal file
204
drv/usart_regs.h
Normal file
@ -0,0 +1,204 @@
|
||||
/** @file usart_regs.h
|
||||
* Module defining the USART registers.
|
||||
*
|
||||
* Mainly made to be used by the usart module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _USART_REGS_H_
|
||||
#define _USART_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "reg.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define USART1_BASE_ADDRESS 0x40013800
|
||||
#define USART2_BASE_ADDRESS 0x40004400
|
||||
#define USART3_BASE_ADDRESS 0x40004800
|
||||
|
||||
union USART_SR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t PE:1;
|
||||
uint32_t FE:1;
|
||||
uint32_t NE:1;
|
||||
uint32_t ORE:1;
|
||||
uint32_t IDLE:1;
|
||||
uint32_t RXNE:1;
|
||||
uint32_t TC:1;
|
||||
uint32_t TXE:1;
|
||||
uint32_t LBD:1;
|
||||
uint32_t CTS:1;
|
||||
uint32_t reserved1:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_SR_PE reg_def( 0, 1)
|
||||
#define USART_SR_FE reg_def( 1, 1)
|
||||
#define USART_SR_NE reg_def( 2, 1)
|
||||
#define USART_SR_ORE reg_def( 3, 1)
|
||||
#define USART_SR_IDLE reg_def( 4, 1)
|
||||
#define USART_SR_RXNE reg_def( 5, 1)
|
||||
#define USART_SR_TC reg_def( 6, 1)
|
||||
#define USART_SR_TXE reg_def( 7, 1)
|
||||
#define USART_SR_LBD reg_def( 8, 1)
|
||||
#define USART_SR_CTS reg_def( 9, 1)
|
||||
#define USART_SR_reserved1 reg_def(10, 22)
|
||||
|
||||
union USART_DR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t DR:9;
|
||||
uint32_t reserved1:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_DR_DR reg_def( 0, 9)
|
||||
#define USART_DR_reserved1 reg_def( 9, 23)
|
||||
|
||||
union USART_BRR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t DIV_Fraction:4;
|
||||
uint32_t DIV_Mantissa:12;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_BRR_DIV_Fraction reg_def( 0, 4)
|
||||
#define USART_BRR_DIV_Mantissa reg_def( 4, 12)
|
||||
#define USART_BRR_reserved1 reg_def(16, 16)
|
||||
|
||||
union USART_CR1 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t SBK:1;
|
||||
uint32_t RWU:1;
|
||||
uint32_t RE:1;
|
||||
uint32_t TE:1;
|
||||
uint32_t IDLEIE:1;
|
||||
uint32_t RXNEIE:1;
|
||||
uint32_t TCIE:1;
|
||||
uint32_t TXEIE:1;
|
||||
uint32_t PEI:1;
|
||||
uint32_t PS:1;
|
||||
uint32_t PCE:1;
|
||||
uint32_t WAKE:1;
|
||||
uint32_t M:1;
|
||||
uint32_t UE:1;
|
||||
uint32_t reserved1:18;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_CR1_SBK reg_def( 0, 1)
|
||||
#define USART_CR1_RWU reg_def( 1, 1)
|
||||
#define USART_CR1_RE reg_def( 2, 1)
|
||||
#define USART_CR1_TE reg_def( 3, 1)
|
||||
#define USART_CR1_IDLEIE reg_def( 4, 1)
|
||||
#define USART_CR1_RXNEIE reg_def( 5, 1)
|
||||
#define USART_CR1_TCIE reg_def( 6, 1)
|
||||
#define USART_CR1_TXEIE reg_def( 7, 1)
|
||||
#define USART_CR1_PEI reg_def( 8, 1)
|
||||
#define USART_CR1_PS reg_def( 9, 1)
|
||||
#define USART_CR1_PCE reg_def(10, 1)
|
||||
#define USART_CR1_WAKE reg_def(11, 1)
|
||||
#define USART_CR1_M reg_def(12, 1)
|
||||
#define USART_CR1_UE reg_def(13, 1)
|
||||
#define USART_CR1_reserved1 reg_def(14, 18)
|
||||
|
||||
union USART_CR2 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t ADD:4;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t LBDL:1;
|
||||
uint32_t LBDIE:1;
|
||||
uint32_t reserved2:1;
|
||||
uint32_t LBCL:1;
|
||||
uint32_t CPHA:1;
|
||||
uint32_t CPOL:1;
|
||||
uint32_t CLKEN:1;
|
||||
uint32_t STOP:2;
|
||||
uint32_t LINEN:1;
|
||||
uint32_t reserved3:17;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_CR2_ADD reg_def( 0, 4)
|
||||
#define USART_CR2_reserved1 reg_def( 4, 1)
|
||||
#define USART_CR2_LBDL reg_def( 5, 1)
|
||||
#define USART_CR2_LBDIE reg_def( 6, 1)
|
||||
#define USART_CR2_reserved2 reg_def( 7, 1)
|
||||
#define USART_CR2_LBCL reg_def( 8, 1)
|
||||
#define USART_CR2_CPHA reg_def( 9, 1)
|
||||
#define USART_CR2_CPOL reg_def(10, 1)
|
||||
#define USART_CR2_CLKEN reg_def(11, 1)
|
||||
#define USART_CR2_STOP reg_def(12, 2)
|
||||
#define USART_CR2_LINEN reg_def(14, 1)
|
||||
#define USART_CR2_reserved3 reg_def(15, 17)
|
||||
|
||||
union USART_CR3 {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t EIE:1;
|
||||
uint32_t IREN:1;
|
||||
uint32_t IRLP:1;
|
||||
uint32_t HDSEL:1;
|
||||
uint32_t NACK:1;
|
||||
uint32_t SCEN:1;
|
||||
uint32_t DMAR:1;
|
||||
uint32_t DMAT:1;
|
||||
uint32_t RTSE:1;
|
||||
uint32_t CTSE:1;
|
||||
uint32_t CTSIE:1;
|
||||
uint32_t reserved3:21;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_CR3_EIE reg_def( 0, 1)
|
||||
#define USART_CR3_IREN reg_def( 1, 1)
|
||||
#define USART_CR3_IRLP reg_def( 2, 1)
|
||||
#define USART_CR3_HDSEL reg_def( 3, 1)
|
||||
#define USART_CR3_NACK reg_def( 4, 1)
|
||||
#define USART_CR3_SCEN reg_def( 5, 1)
|
||||
#define USART_CR3_DMAR reg_def( 6, 1)
|
||||
#define USART_CR3_DMAT reg_def( 7, 1)
|
||||
#define USART_CR3_RTSE reg_def( 8, 1)
|
||||
#define USART_CR3_CTSE reg_def( 9, 1)
|
||||
#define USART_CR3_CTSIE reg_def(10, 1)
|
||||
#define USART_CR3_reserved3 reg_def(11, 21)
|
||||
|
||||
union USART_GTPR {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t PSC:8;
|
||||
uint32_t GT:8;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
#define USART_GTPR_PSC reg_def( 0, 8)
|
||||
#define USART_GTPR_GT reg_def( 8, 8)
|
||||
#define USART_GTPR_reserved1 reg_def(16, 16)
|
||||
|
||||
struct USART {
|
||||
union USART_SR SR;
|
||||
union USART_DR DR;
|
||||
union USART_BRR BRR;
|
||||
union USART_CR1 CR1;
|
||||
union USART_CR2 CR2;
|
||||
union USART_CR3 CR3;
|
||||
union USART_GTPR GTPR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_USART_REGS_H_
|
||||
|
||||
82
linker.ld
Normal file
82
linker.ld
Normal file
@ -0,0 +1,82 @@
|
||||
/** @file
|
||||
* Linker to be used with the HBL.
|
||||
*
|
||||
* This linker file provides the basic architecture for a projet. Stack size and
|
||||
* memory layout can be configured at will. Note that this file doesn't provide
|
||||
* a heap space since the HBL doesn't provide or use any form of dynamic
|
||||
* allocation.
|
||||
*/
|
||||
|
||||
/*--Configuration-------------------------------------------------------------*/
|
||||
|
||||
/* minimal stack size */
|
||||
_min_stack_size = 0x400;
|
||||
|
||||
/* memory layout of the chip */
|
||||
MEMORY
|
||||
{
|
||||
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
RAM (!rx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
/*--Description---------------------------------------------------------------*/
|
||||
|
||||
ENTRY(hdr_reset)
|
||||
|
||||
/* end of "RAM" Ram type memory */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
/* ROM adress to load data from */
|
||||
_sromdata = LOADADDR(.data);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* vector table, cpu will look for it at adress 0 on reset */
|
||||
.vector_table :
|
||||
{
|
||||
KEEP(*(.vector_table))
|
||||
} > ROM
|
||||
|
||||
/* program code */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
} > ROM
|
||||
|
||||
/* const data */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata)
|
||||
} > ROM
|
||||
|
||||
/* initialized data from ROM */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .;
|
||||
*(.data)
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} > RAM AT > ROM
|
||||
|
||||
/* uninitialized data, zeroed */
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sbss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} > RAM
|
||||
|
||||
/* memory space allocated to stack. The stack is situated at the very end of
|
||||
* the RAM while this section may not, thus it is only used to enforce a
|
||||
* minimal stack size */
|
||||
.stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
. = . + _min_stack_size;
|
||||
} > RAM
|
||||
}
|
||||
|
||||
3
openocd
3
openocd
@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
openocd -f interface/stlink.cfg -f target/cs32f1x.cfg
|
||||
|
||||
29
src/config.h
29
src/config.h
@ -1,29 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/* priorities */
|
||||
#define EXTI0_IRQ_PRIORITY 8
|
||||
#define EXTI1_IRQ_PRIORITY 8
|
||||
#define EXTI2_IRQ_PRIORITY 8
|
||||
#define EXTI3_IRQ_PRIORITY 8
|
||||
#define EXTI4_IRQ_PRIORITY 8
|
||||
#define EXTI9_5_IRQ_PRIORITY 8
|
||||
#define EXTI15_10_IRQ_PRIORITY 8
|
||||
|
||||
#define TIM1_IRQ_PRIORITY 4
|
||||
#define TIM2_IRQ_PRIORITY 4
|
||||
#define TIM3_IRQ_PRIORITY 4
|
||||
#define TIM4_IRQ_PRIORITY 4
|
||||
|
||||
#define USART1_IRQ_PRIORITY 3
|
||||
#define USART2_IRQ_PRIORITY 3
|
||||
#define USART3_IRQ_PRIORITY 3
|
||||
|
||||
#define I2C1_IRQ_PRIORITY 2
|
||||
#define I2C1_IRQERR_PRIORITY 1
|
||||
#define I2C2_IRQ_PRIORITY 2
|
||||
#define I2C2_IRQERR_PRIORITY 1
|
||||
|
||||
#define SPI1_IRQ_PRIORITY 4
|
||||
#define SPI2_IRQ_PRIORITY 4
|
||||
|
||||
#define ADC1_2_IRQ_PRIORITY 5
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
#include "adc.h"
|
||||
|
||||
extern Clock_t sysclks;
|
||||
|
||||
int adc_init(ADC_TypeDef* adc) {
|
||||
// enable adc clock
|
||||
if(adc == ADC1) RCC->APB2ENR |= 0x1 << 9;
|
||||
else if(adc == ADC2) RCC->APB2ENR |= 0x1 << 10;
|
||||
else return -1; //no such adc
|
||||
|
||||
// enable adc
|
||||
adc->CR2 |= 0x1;
|
||||
|
||||
// configure regular channels
|
||||
adc->CR1 = 0; //reset value
|
||||
adc->CR1 |= 0x1 << 23; //enable analog watchdog
|
||||
adc->CR1 |= 0x1 << 11; //discontinuous mode
|
||||
|
||||
// set trigger to manual
|
||||
adc->CR1 |= 0x7 << 3;
|
||||
adc->SMPR2 |= 0x3FFFFFFF;
|
||||
|
||||
// calibrate
|
||||
adc->CR2 |= 0x1 << 2;
|
||||
while((adc->CR2 >> 2) & 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t adc_read(ADC_TypeDef* adc, uint8_t channel) {
|
||||
|
||||
adc->SQR1 &= ~(0xF << 20); //one conversion only
|
||||
adc->SQR3 = (adc->SQR3 & ~(0x1F)) | channel; //set channel
|
||||
|
||||
//adc->CR2 |= 0x1 << 22; //start convertion
|
||||
adc->CR2 |= 0x1;
|
||||
while(!((adc->SR >> 1) & 0x1)); //waiting for convertion
|
||||
|
||||
return adc->DR & 0xFFF;
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
#ifndef ADC_H
|
||||
#define ADC_H
|
||||
|
||||
#include "../target/stm32f103xb.h"
|
||||
#include "../config.h"
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
int adc_init(ADC_TypeDef* adc);
|
||||
|
||||
uint16_t adc_read(ADC_TypeDef* adc, uint8_t channel);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
223
src/drivers/io.c
223
src/drivers/io.c
@ -1,223 +0,0 @@
|
||||
//driver header
|
||||
#include "io.h"
|
||||
|
||||
static OnIO io_cb[16]={
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
void EXTI0_IRQHandler() {
|
||||
if (io_cb[0]) (io_cb[0])();
|
||||
EXTI->PR = 1<<0;
|
||||
}
|
||||
|
||||
void EXTI1_IRQHandler() {
|
||||
if (io_cb[1]) (io_cb[1])();
|
||||
EXTI->PR = 1<<1;
|
||||
}
|
||||
|
||||
void EXTI2_IRQHandler() {
|
||||
if (io_cb[2]) (io_cb[2])();
|
||||
EXTI->PR = 1<<2;
|
||||
}
|
||||
|
||||
void EXTI3_IRQHandler() {
|
||||
if (io_cb[3]) (io_cb[3])();
|
||||
EXTI->PR = 1<<3;
|
||||
}
|
||||
|
||||
void EXTI4_IRQHandler() {
|
||||
if (io_cb[4]) (io_cb[4])();
|
||||
EXTI->PR = 1<<4;
|
||||
}
|
||||
|
||||
void EXTI9_5_IRQHandler() {
|
||||
if (EXTI->PR & (1<<5)) {
|
||||
if (io_cb[5]) (io_cb[5])();
|
||||
EXTI->PR = 1<<5;
|
||||
} else if (EXTI->PR & (1<<6)) {
|
||||
if (io_cb[6]) (io_cb[6])();
|
||||
EXTI->PR = 1<<6;
|
||||
} else if (EXTI->PR & (1<<7)) {
|
||||
if (io_cb[7]) (io_cb[7])();
|
||||
EXTI->PR = 1<<7;
|
||||
} else if (EXTI->PR & (1<<8)) {
|
||||
if (io_cb[8]) (io_cb[8])();
|
||||
EXTI->PR = 1<<8;
|
||||
} else if (EXTI->PR & (1<<9)) {
|
||||
if (io_cb[9]) (io_cb[9])();
|
||||
EXTI->PR = 1<<9;
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI15_10_IRQHandler() {
|
||||
if (EXTI->PR & (1<<10)) {
|
||||
if (io_cb[10]) (io_cb[10])();
|
||||
EXTI->PR = 1<<10;
|
||||
} else if (EXTI->PR & (1<<11)) {
|
||||
if (io_cb[11]) (io_cb[11])();
|
||||
EXTI->PR = 1<<11;
|
||||
} else if (EXTI->PR & (1<<12)) {
|
||||
if (io_cb[12]) (io_cb[12])();
|
||||
EXTI->PR = 1<<12;
|
||||
} else if (EXTI->PR & (1<<13)) {
|
||||
if (io_cb[13]) (io_cb[13])();
|
||||
EXTI->PR = 1<<13;
|
||||
} else if (EXTI->PR & (1<<14)) {
|
||||
if (io_cb[14]) (io_cb[14])();
|
||||
EXTI->PR = 1<<14;
|
||||
} else if (EXTI->PR & (1<<15)) {
|
||||
if (io_cb[15]) (io_cb[15])();
|
||||
EXTI->PR = 1<<15;
|
||||
}
|
||||
}
|
||||
|
||||
/* Definitions for EXTI configuration */
|
||||
enum io_exti_mask {
|
||||
SYSCFG_EXTI_PA_MASK = 0x0,
|
||||
SYSCFG_EXTI_PB_MASK = 0x1,
|
||||
SYSCFG_EXTI_PC_MASK = 0x2,
|
||||
SYSCFG_EXTI_PD_MASK = 0x3,
|
||||
SYSCFG_EXTI_PE_MASK = 0x4
|
||||
};
|
||||
|
||||
int io_configure(GPIO_TypeDef *gpio, uint16_t pin, uint16_t pin_cfg, OnIO cb) {
|
||||
|
||||
// enable GPIOx subsystem clocking
|
||||
if (gpio == GPIOA) RCC->APB2ENR |= 1<<2;
|
||||
else if (gpio == GPIOB) RCC->APB2ENR |= 1<<3;
|
||||
else if (gpio == GPIOC) RCC->APB2ENR |= 1<<4;
|
||||
else if (gpio == GPIOD) RCC->APB2ENR |= 1<<5;
|
||||
else if (gpio == GPIOE) RCC->APB2ENR |= 1<<6;
|
||||
|
||||
// setup pin mask for crx registers
|
||||
uint64_t pin_mask = 0;
|
||||
for(int i=0; i<16; ++i) {
|
||||
if((pin >> i) & 0x1) pin_mask |= 0x1ll << 4*i;
|
||||
}
|
||||
|
||||
// clear previous data
|
||||
uint64_t crx = pin_mask * 0x4; //reset value is 0x4
|
||||
uint16_t odr = pin;
|
||||
gpio->CRH &= ~(crx >> 32);
|
||||
gpio->CRL &= ~(crx & 0xFFFFFFFF);
|
||||
gpio->BSRR |= odr << 16;
|
||||
|
||||
// set up the new configuration
|
||||
crx = pin_mask * (pin_cfg & 0xF);
|
||||
odr = pin * ((pin_cfg & 0x10) >> 4);
|
||||
gpio->CRH |= crx >> 32;
|
||||
gpio->CRL |= crx & 0xFFFFFFFF;
|
||||
gpio->BSRR |= odr;
|
||||
|
||||
//TODO manage alternate functions
|
||||
|
||||
// manage IRQs //TODO allow IRQ reset
|
||||
if (!cb) return 0; //no callback attached
|
||||
|
||||
if (pin_cfg & 0x7) return -1; //callback set, but not in input mode
|
||||
|
||||
RCC->APB2ENR |= 0x1; //enable AFIO clocking
|
||||
|
||||
// prepare mask
|
||||
uint8_t port_mask = 0;
|
||||
// uint32_t pin_mask = 0;
|
||||
if (gpio == GPIOA) port_mask = SYSCFG_EXTI_PA_MASK;
|
||||
else if (gpio == GPIOB) port_mask = SYSCFG_EXTI_PB_MASK;
|
||||
else if (gpio == GPIOC) port_mask = SYSCFG_EXTI_PC_MASK;
|
||||
else if (gpio == GPIOD) port_mask = SYSCFG_EXTI_PD_MASK;
|
||||
else if (gpio == GPIOE) port_mask = SYSCFG_EXTI_PE_MASK;
|
||||
|
||||
// setup external IRQ lines
|
||||
uint64_t afio_mask;
|
||||
for(int i=0; i<4; ++i) {
|
||||
afio_mask = ((pin_mask & (0xFFFFll << (i*16))) >> (i*16)) * port_mask;
|
||||
if(afio_mask) AFIO->EXTICR[i] |= afio_mask;
|
||||
}
|
||||
|
||||
// clear pending IRQs on concerned lines
|
||||
EXTI->PR |= pin;
|
||||
|
||||
// configure IRQ options and masks
|
||||
EXTI->IMR |= pin;
|
||||
if(pin_cfg & 0x100) EXTI->RTSR |= pin;
|
||||
if(pin_cfg & 0x200) EXTI->FTSR |= pin; //in case both falling and rising
|
||||
//are set, both will be a trigger
|
||||
|
||||
// register IRQ callbacks
|
||||
for(int i=0; i<16; ++i) {
|
||||
if((pin >> i) & 0x1) {
|
||||
io_cb[i] = cb;
|
||||
|
||||
// Setup NVIC
|
||||
switch (i) {
|
||||
case 0:
|
||||
NVIC_SetPriority(EXTI0_IRQn, EXTI0_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI0_IRQn);
|
||||
break;
|
||||
case 1:
|
||||
NVIC_SetPriority(EXTI1_IRQn, EXTI1_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI1_IRQn);
|
||||
break;
|
||||
case 2:
|
||||
NVIC_SetPriority(EXTI2_IRQn, EXTI2_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI2_IRQn);
|
||||
break;
|
||||
case 3:
|
||||
NVIC_SetPriority(EXTI3_IRQn, EXTI3_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI3_IRQn);
|
||||
break;
|
||||
case 4:
|
||||
NVIC_SetPriority(EXTI4_IRQn, EXTI4_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI4_IRQn);
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
NVIC_SetPriority(EXTI9_5_IRQn, EXTI9_5_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI9_5_IRQn);
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
NVIC_SetPriority(EXTI15_10_IRQn, EXTI15_10_IRQ_PRIORITY);
|
||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||
break;
|
||||
default:
|
||||
return -1; //impossible to get there
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t io_read(GPIO_TypeDef *gpio, uint16_t mask)
|
||||
{
|
||||
return gpio->IDR & mask;
|
||||
}
|
||||
|
||||
void io_write(GPIO_TypeDef *gpio, uint16_t val, uint16_t mask)
|
||||
{
|
||||
gpio->BSRR = (uint32_t)(mask) << (val ? 0 : 16);
|
||||
}
|
||||
|
||||
void io_write_n(GPIO_TypeDef *gpio, uint16_t val, uint16_t mask)
|
||||
{
|
||||
gpio->BSRR = (uint32_t)(mask) << (val ? 16 : 0);
|
||||
}
|
||||
|
||||
void io_set(GPIO_TypeDef *gpio, uint16_t mask)
|
||||
{
|
||||
gpio->BSRR = mask;
|
||||
}
|
||||
|
||||
void io_clear(GPIO_TypeDef *gpio, uint16_t mask)
|
||||
{
|
||||
gpio->BSRR = (uint32_t)(mask) << 16;
|
||||
}
|
||||
132
src/drivers/io.h
132
src/drivers/io.h
@ -1,132 +0,0 @@
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
//std headers
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//target header
|
||||
#include "../target/stm32f103xb.h"
|
||||
|
||||
//custom header
|
||||
#include "../config.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* GPIO pin mask definitions */
|
||||
enum io_pin {
|
||||
PIN_0 = (1 << 0),
|
||||
PIN_1 = (1 << 1),
|
||||
PIN_2 = (1 << 2),
|
||||
PIN_3 = (1 << 3),
|
||||
PIN_4 = (1 << 4),
|
||||
PIN_5 = (1 << 5),
|
||||
PIN_6 = (1 << 6),
|
||||
PIN_7 = (1 << 7),
|
||||
PIN_8 = (1 << 8),
|
||||
PIN_9 = (1 << 9),
|
||||
PIN_10 = (1 << 10),
|
||||
PIN_11 = (1 << 11),
|
||||
PIN_12 = (1 << 12),
|
||||
PIN_13 = (1 << 13),
|
||||
PIN_14 = (1 << 14),
|
||||
PIN_15 = (1 << 15),
|
||||
PIN_ALL = 0xFFFF
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* GPIO pin mode definitions */
|
||||
enum io_mode {
|
||||
IO_MODE_INPUT = (0x0),
|
||||
IO_MODE_OUTPUT = (0x1), // 10Mhz max
|
||||
IO_MODE_OUTPUT_SLOW = (0x3), // 2MHz max
|
||||
IO_MODE_OUTPUT_FAST = (0x4) // 50 MHz max
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* GPIO pin conf definitions */
|
||||
enum io_conf {
|
||||
IO_IN_ANALOG = (0b0 << 2),
|
||||
IO_IN_FLOATING = (0b1 << 2),
|
||||
IO_IN_PULL_UP = (0b110 << 2),
|
||||
IO_IN_PULL_DOWN = (0b010 << 2),
|
||||
IO_OUT_ALT_FNCT = (0b10 << 2),
|
||||
IO_OUT_PUSH_PULL = (0b0 << 2),
|
||||
IO_OUT_OPEN_DRAIN = (0b1 << 2)
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* GPIO pin clear */
|
||||
#define IO_CLEAR (0)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* alternate function selection option */
|
||||
//TODO not supported for now
|
||||
//enum io_alt_fnct {
|
||||
// PIN_OPT_AF0 0x0,
|
||||
// PIN_OPT_AF1 0x1,
|
||||
// PIN_OPT_AF2 0x2,
|
||||
// PIN_OPT_AF3 0x3,
|
||||
// PIN_OPT_AF4 0x4,
|
||||
// PIN_OPT_AF5 0x5,
|
||||
// PIN_OPT_AF6 0x6,
|
||||
// PIN_OPT_AF7 0x7,
|
||||
// PIN_OPT_AF8 0x8,
|
||||
// PIN_OPT_AF9 0x9,
|
||||
// PIN_OPT_AF10 0xA,
|
||||
// PIN_OPT_AF11 0xB,
|
||||
// PIN_OPT_AF12 0xC,
|
||||
// PIN_OPT_AF13 0xD,
|
||||
// PIN_OPT_AF14 0xE,
|
||||
// PIN_OPT_AF15 0xF
|
||||
//};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* GPIO IRQ conf definitons */
|
||||
enum io_irq_conf {
|
||||
IO_IRQ_EDGE_RISE = (0x1 << 8),
|
||||
IO_IRQ_EDGE_FALL = (0x2 << 8),
|
||||
IO_IRQ_EDGE_BOTH = (0x3 << 8)
|
||||
};
|
||||
|
||||
typedef void (*OnIO)();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* io_configure
|
||||
*
|
||||
* configure pins referenced in 'pin_mask' of specified port
|
||||
* 'gpio' according to 'pin_cfg' and associate a callback
|
||||
* function 'cb' if not NULL.
|
||||
* returns 0 if success
|
||||
*/
|
||||
int io_configure(GPIO_TypeDef *gpio, uint16_t pin_mask, uint16_t pin_cfg,
|
||||
OnIO cb);
|
||||
|
||||
/* io_read
|
||||
*
|
||||
* read 32 bit data from port 'gpio', filter the result with mask
|
||||
*/
|
||||
uint32_t io_read(GPIO_TypeDef *gpio, uint16_t mask);
|
||||
|
||||
/* io_write
|
||||
*
|
||||
* write 16 bit data filtered by mask to port 'gpio'
|
||||
* '1' in val are written as HIGH level on port pins
|
||||
*/
|
||||
void io_write(GPIO_TypeDef *gpio, uint16_t val, uint16_t mask);
|
||||
|
||||
/* io_write_n
|
||||
*
|
||||
* write 16 bit data filtered by mask to port 'gpio'
|
||||
* '1' in val are written as LOW level on port pins
|
||||
*/
|
||||
void io_write_n(GPIO_TypeDef *gpio, uint16_t val, uint16_t mask);
|
||||
|
||||
/* io_set/clear
|
||||
*
|
||||
* set or clear outputs according to bit mask
|
||||
*/
|
||||
void io_set(GPIO_TypeDef *gpio, uint16_t mask);
|
||||
void io_clear(GPIO_TypeDef *gpio, uint16_t mask);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,186 +0,0 @@
|
||||
#include "lcd.h"
|
||||
|
||||
enum mode {
|
||||
WRITE,
|
||||
READ,
|
||||
UNDEFINED
|
||||
};
|
||||
|
||||
//TODO make the driver dynamic ?
|
||||
static TIM_TypeDef* timer = 0;
|
||||
static uint8_t mode = UNDEFINED;
|
||||
static uint8_t rows = 0;
|
||||
static uint8_t columns = 0;
|
||||
static uint8_t rows_offset[4] = {};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// internal functions
|
||||
int set_mode_read(void) {
|
||||
// configure pins
|
||||
if(io_configure(GPIOA, PIN_8 | PIN_12 | PIN_15, IO_MODE_INPUT |
|
||||
IO_IN_FLOATING, 0)) return -1;
|
||||
if(io_configure(GPIOB, PIN_3 | PIN_4 | PIN_13 | PIN_14 | PIN_15,
|
||||
IO_MODE_INPUT | IO_IN_FLOATING, 0)) return -1;
|
||||
|
||||
// put lcd in read mode
|
||||
io_set(GPIOA, PIN_9); // after the pins are ready to recieve voltage
|
||||
mode = READ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_mode_write(void) {
|
||||
// put lcd in write mode
|
||||
io_clear(GPIOA, PIN_9); //before the pin can send voltage
|
||||
|
||||
// configure pins
|
||||
if(io_configure(GPIOA, PIN_8 | PIN_12 | PIN_15, IO_MODE_OUTPUT |
|
||||
IO_OUT_PUSH_PULL, 0)) return -1;
|
||||
if(io_configure(GPIOB, PIN_3 | PIN_4 | PIN_13 | PIN_14 | PIN_15,
|
||||
IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0)) return -1;
|
||||
mode = WRITE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wait_for_ready(void) {
|
||||
//TODO debug that
|
||||
// // configure the lcd
|
||||
// if(mode != READ) if(set_mode_read()) return;
|
||||
//
|
||||
// // read D7 pin
|
||||
// for(;;) {
|
||||
// io_set(GPIOA, PIN_11);
|
||||
// for(int i=0; i<1000; ++i); //timer_wait is overkill here
|
||||
// if(!io_read(GPIOB, PIN_4)) break;
|
||||
// io_clear(GPIOA, PIN_11);
|
||||
// for(int i=0; i<1000; ++i); //same
|
||||
// }
|
||||
timer_wait_ms(timer, 2, 0); //wait max delay
|
||||
}
|
||||
|
||||
void write_byte(uint8_t byte) {
|
||||
// put the lcd bus in write mode
|
||||
if(mode != WRITE) if(set_mode_write()) return;
|
||||
|
||||
// start tranfert
|
||||
io_set(GPIOA, PIN_11);
|
||||
timer_wait_us(timer, 1, 0);
|
||||
|
||||
// send the data
|
||||
io_write(GPIOA, (byte >> 0) & 0x1, PIN_8);
|
||||
io_write(GPIOA, (byte >> 1) & 0x1, PIN_12);
|
||||
io_write(GPIOB, (byte >> 2) & 0x1, PIN_15);
|
||||
io_write(GPIOA, (byte >> 3) & 0x1, PIN_15);
|
||||
io_write(GPIOB, (byte >> 4) & 0x1, PIN_14);
|
||||
io_write(GPIOB, (byte >> 5) & 0x1, PIN_3);
|
||||
io_write(GPIOB, (byte >> 6) & 0x1, PIN_13);
|
||||
io_write(GPIOB, (byte >> 7) & 0x1, PIN_4);
|
||||
|
||||
// validate data
|
||||
io_clear(GPIOA, PIN_11);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int lcd_init(TIM_TypeDef* tim, uint8_t col, uint8_t row) {
|
||||
|
||||
timer = tim;
|
||||
columns = col;
|
||||
rows = row;
|
||||
rows_offset[0] = 0x00;
|
||||
rows_offset[1] = 0x40;
|
||||
rows_offset[2] = 0x00 + columns;
|
||||
rows_offset[3] = 0x40 + columns;
|
||||
|
||||
// disable JTAG, as it utilise needed pins, SWD remains usable in
|
||||
// synchronous mode
|
||||
RCC->APB2ENR |= 0x1; //enable AFIO clocking
|
||||
AFIO->MAPR = (AFIO->MAPR & ~(0x8 << 24)) | 0x2 << 24;
|
||||
|
||||
// configure the lcd control pins
|
||||
if(io_configure(GPIOA, PIN_9 | PIN_10 | PIN_11, IO_MODE_OUTPUT |
|
||||
IO_OUT_PUSH_PULL, 0)) return -1;
|
||||
|
||||
// put the lcd bus in write mode
|
||||
if(set_mode_write()) return -1; //no check in case the pins were used
|
||||
//somewhere else
|
||||
|
||||
// select instruction register
|
||||
io_write(GPIOA, LCD_MODE_CMD, PIN_10);
|
||||
|
||||
// begin initialisation sequence
|
||||
timer_wait_ms(timer, 15, 0);
|
||||
write_byte(LCD_FUNC_SET | LCD_FUNC_8BIT | LCD_FUNC_2LINE |
|
||||
LCD_FUNC_5x8DOTS);
|
||||
timer_wait_ms(timer, 5, 0);
|
||||
write_byte(LCD_FUNC_SET | LCD_FUNC_8BIT | LCD_FUNC_2LINE |
|
||||
LCD_FUNC_5x8DOTS);
|
||||
timer_wait_us(timer, 150, 0);
|
||||
write_byte(LCD_FUNC_SET | LCD_FUNC_8BIT | LCD_FUNC_2LINE |
|
||||
LCD_FUNC_5x8DOTS);
|
||||
wait_for_ready();
|
||||
write_byte(LCD_FUNC_SET | LCD_FUNC_8BIT | LCD_FUNC_2LINE |
|
||||
LCD_FUNC_5x8DOTS);
|
||||
wait_for_ready();
|
||||
write_byte(LCD_DISP_CTRL | LCD_CTRL_DISP_OFF | LCD_CTRL_CUR_OFF |
|
||||
LCD_CTRL_BLINK_OFF);
|
||||
wait_for_ready();
|
||||
write_byte(LCD_CLEAR);
|
||||
wait_for_ready();
|
||||
write_byte(LCD_ENTRY | LCD_ENTRY_LEFT | LCD_ENTRY_SHIFT_DEC);
|
||||
wait_for_ready();
|
||||
|
||||
// post initialisation setup
|
||||
write_byte(LCD_DISP_CTRL | LCD_CTRL_DISP_ON | LCD_CTRL_CUR_ON |
|
||||
LCD_CTRL_BLINK_ON);
|
||||
wait_for_ready();
|
||||
write_byte(LCD_CLEAR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lcd_send_cmd(uint8_t cmd) {
|
||||
// wait for the screen
|
||||
wait_for_ready();
|
||||
|
||||
// select instruction register
|
||||
io_write(GPIOA, LCD_MODE_CMD, PIN_10);
|
||||
|
||||
// send the command
|
||||
write_byte(cmd);
|
||||
}
|
||||
|
||||
void lcd_print(const char* txt) {
|
||||
// prepare data
|
||||
const char* c = txt;
|
||||
|
||||
// wait for the screen
|
||||
wait_for_ready();
|
||||
|
||||
// select data register
|
||||
io_write(GPIOA, LCD_MODE_DATA, PIN_10);
|
||||
|
||||
// send the caracters until end of string
|
||||
// TODO implement '\n'
|
||||
while(*c != '\0') {
|
||||
wait_for_ready();
|
||||
write_byte(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_print_c(char c) {
|
||||
// wait for the screen
|
||||
wait_for_ready();
|
||||
|
||||
// select data register
|
||||
io_write(GPIOA, LCD_MODE_DATA, PIN_10);
|
||||
|
||||
// send the caracter
|
||||
write_byte(c);
|
||||
}
|
||||
|
||||
void lcd_set_cursor(uint8_t col, uint8_t row) {
|
||||
lcd_send_cmd(LCD_DDRAM_ADDR | (col + rows_offset[row]));
|
||||
}
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
#ifndef LCD_H
|
||||
#define LCD_H
|
||||
|
||||
#include "../target/stm32f103xb.h"
|
||||
#include "../config.h"
|
||||
#include "timer.h"
|
||||
#include "io.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* LCD mode selection */
|
||||
enum lcd_register {
|
||||
LCD_MODE_CMD = 0,
|
||||
LCD_MODE_DATA = 1
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* LCD commands */
|
||||
enum lcd_command {
|
||||
LCD_CLEAR = 0x01,
|
||||
LCD_CUR_HOME = 0x02,
|
||||
LCD_ENTRY = 0x04,
|
||||
LCD_DISP_CTRL = 0x08,
|
||||
LCD_SHIFT = 0x10,
|
||||
LCD_FUNC_SET = 0x20,
|
||||
LCD_CGRAM_ADDR = 0x40,
|
||||
LCD_DDRAM_ADDR = 0x80
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* LCD_ENTRY command options */
|
||||
enum lcd_entry_option {
|
||||
LCD_ENTRY_RIGHT = 0x00,
|
||||
LCD_ENTRY_LEFT = 0x02,
|
||||
LCD_ENTRY_SHIFT_INC = 0x01,
|
||||
LCD_ENTRY_SHIFT_DEC = 0x00
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* LCD_DISP_CTRL command options */
|
||||
enum lcd_ctrl_option {
|
||||
LCD_CTRL_DISP_ON = 0x04,
|
||||
LCD_CTRL_DISP_OFF = 0x00,
|
||||
LCD_CTRL_CUR_ON = 0x02,
|
||||
LCD_CTRL_CUR_OFF = 0x00,
|
||||
LCD_CTRL_BLINK_ON = 0x01,
|
||||
LCD_CTRL_BLINK_OFF = 0x00
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* LCD_SHIFT command options */
|
||||
enum lcd_shift_option {
|
||||
LCD_SHIFT_DISP = 0x08,
|
||||
LCD_SHIFT_CUR = 0x00,
|
||||
LCD_SHIFT_RIGHT = 0x04,
|
||||
LCD_SHIFT_LEFT = 0x00
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* LCD_FUNC_SET command options */
|
||||
enum lcd_func_option {
|
||||
LCD_FUNC_8BIT = 0x10,
|
||||
LCD_FUNC_4BIT = 0x00,
|
||||
LCD_FUNC_2LINE = 0x08,
|
||||
LCD_FUNC_1LINE = 0x00,
|
||||
LCD_FUNC_5x10DOTS = 0x04,
|
||||
LCD_FUNC_5x8DOTS = 0x00
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** lcd_init
|
||||
* initialise the lcd, needed before anything else can be done
|
||||
* the timer is used for delays and can't be in use when lcd functions are
|
||||
* called
|
||||
*/
|
||||
int lcd_init(TIM_TypeDef* tim, uint8_t col, uint8_t row);
|
||||
|
||||
/** lcd_send_cmd
|
||||
* send the specified command to the lcd
|
||||
*/
|
||||
void lcd_send_cmd(uint8_t cmd);
|
||||
|
||||
/** lcd_print
|
||||
* print a null-terminated string on the lcd
|
||||
*/
|
||||
void lcd_print(const char* txt);
|
||||
|
||||
void lcd_print_c(char c);
|
||||
|
||||
void lcd_set_cursor(uint8_t col, uint8_t row);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,258 +0,0 @@
|
||||
/*
|
||||
==============================================================================
|
||||
##### RCC specific features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
After reset the device is running from Internal High Speed oscillator
|
||||
(HSI 16MHz) with Flash 0 wait state, Flash prefetch buffer, D-Cache
|
||||
and I-Cache are disabled, and all peripherals are off except internal
|
||||
SRAM, Flash and JTAG.
|
||||
(+) There is no prescaler on High speed (AHB) and Low speed (APB) busses;
|
||||
all peripherals mapped on these busses are running at HSI speed.
|
||||
(+) The clock for all peripherals is switched off, except the SRAM and FLASH.
|
||||
(+) All GPIOs are in input floating state, except the JTAG pins which
|
||||
are assigned to be used for debug purpose.
|
||||
|
||||
[..]
|
||||
Once the device started from reset, the user application has to:
|
||||
(+) Configure the clock source to be used to drive the System clock
|
||||
(if the application needs higher frequency/performance)
|
||||
(+) Configure the System clock frequency and Flash settings
|
||||
(+) Configure the AHB and APB busses prescalers
|
||||
(+) Enable the clock for the peripheral(s) to be used
|
||||
(+) Configure the clock source(s) for peripherals which clocks are not
|
||||
derived from the System clock (I2S, RTC, ADC, USB OTG FS/SDIO/RNG)
|
||||
|
||||
##### RCC Limitations #####
|
||||
==============================================================================
|
||||
[..]
|
||||
A delay between an RCC peripheral clock enable and the effective peripheral
|
||||
enabling should be taken into account in order to manage the peripheral
|
||||
read/write from/to registers.
|
||||
(+) This delay depends on the peripheral mapping.
|
||||
(+) If peripheral is mapped on AHB: the delay is 2 AHB clock cycle
|
||||
after the clock enable bit is set on the hardware register
|
||||
(+) If peripheral is mapped on APB: the delay is 2 APB clock cycle
|
||||
after the clock enable bit is set on the hardware register
|
||||
|
||||
[..]
|
||||
Possible Workarounds:
|
||||
(#) Enable the peripheral clock sometimes before the peripheral read/write
|
||||
register is required.
|
||||
(#) For AHB peripheral, insert two dummy read to the peripheral register.
|
||||
(#) For APB peripheral, insert a dummy read to the peripheral register.
|
||||
*/
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
/* HPRE: AHB high-speed prescaler */
|
||||
#define RCC_CFGR_HPRE_DIV_NONE 0x0
|
||||
#define RCC_CFGR_HPRE_DIV_2 (0x8 + 0)
|
||||
#define RCC_CFGR_HPRE_DIV_4 (0x8 + 1)
|
||||
#define RCC_CFGR_HPRE_DIV_8 (0x8 + 2)
|
||||
#define RCC_CFGR_HPRE_DIV_16 (0x8 + 3)
|
||||
#define RCC_CFGR_HPRE_DIV_64 (0x8 + 4)
|
||||
#define RCC_CFGR_HPRE_DIV_128 (0x8 + 5)
|
||||
#define RCC_CFGR_HPRE_DIV_256 (0x8 + 6)
|
||||
#define RCC_CFGR_HPRE_DIV_512 (0x8 + 7)
|
||||
|
||||
/* PPRE1/2: APB high-speed prescalers */
|
||||
#define RCC_CFGR_PPRE_DIV_NONE 0x0
|
||||
#define RCC_CFGR_PPRE_DIV_2 0x4
|
||||
#define RCC_CFGR_PPRE_DIV_4 0x5
|
||||
#define RCC_CFGR_PPRE_DIV_8 0x6
|
||||
#define RCC_CFGR_PPRE_DIV_16 0x7
|
||||
|
||||
/* PPLMUL: PPL multiplier */
|
||||
#define RCC_CFGR_PLLMUL(fac) (fac + 2)
|
||||
|
||||
/* ADC: ADCPRE prescalers */
|
||||
#define RCC_CFGR_ADCPRE_DIV_2 0x0
|
||||
#define RCC_CFGR_ADCPRE_DIV_4 0x1
|
||||
#define RCC_CFGR_ADCPRE_DIV_6 0x2
|
||||
#define RCC_CFGR_ADCPRE_DIV_8 0x3
|
||||
|
||||
enum rcc_osc {
|
||||
RCC_HSI,
|
||||
RCC_HSE,
|
||||
RCC_PLL,
|
||||
RCC_LSI,
|
||||
RCC_LSE
|
||||
};
|
||||
|
||||
struct ClockConfig_t {
|
||||
uint8_t type;
|
||||
uint8_t pll_src;
|
||||
uint8_t pllmul;
|
||||
uint8_t hpre;
|
||||
uint8_t ppre1;
|
||||
uint8_t ppre2;
|
||||
uint8_t adcpre;
|
||||
uint32_t flash_cfg;
|
||||
uint32_t ahb_freq;
|
||||
uint32_t apb1_freq;
|
||||
uint32_t apb2_freq;
|
||||
};
|
||||
|
||||
static struct ClockConfig_t _clock_config[] = {
|
||||
{/* Performance Mode */
|
||||
.type = RCC_PLL,
|
||||
.pll_src = RCC_HSE, //8MHz
|
||||
.pllmul = RCC_CFGR_PLLMUL(9), //freq should noot exceed 72MHz
|
||||
.hpre = RCC_CFGR_HPRE_DIV_NONE,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV_2, //freq should not exceed 36MHz
|
||||
.ppre2 = RCC_CFGR_PPRE_DIV_NONE,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV_6, //freq should not exceed 14MHz
|
||||
.flash_cfg = FLASH_ACR_LATENCY_2,
|
||||
.ahb_freq = 72000000,
|
||||
.apb1_freq = 36000000,
|
||||
.apb2_freq = 72000000
|
||||
},
|
||||
|
||||
{/* Powersave Mode */
|
||||
.type = RCC_HSE,
|
||||
.hpre = RCC_CFGR_HPRE_DIV_16,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV_16,
|
||||
.ppre2 = RCC_CFGR_PPRE_DIV_16,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV_2,
|
||||
.flash_cfg = FLASH_ACR_LATENCY_0,
|
||||
.ahb_freq = 500000,
|
||||
.apb1_freq = 500000,
|
||||
.apb2_freq = 500000
|
||||
}
|
||||
};
|
||||
|
||||
static void rcc_osc_on(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_HSI:
|
||||
if (!(RCC->CR & RCC_CR_HSION)) {
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
while ((RCC->CR & RCC_CR_HSIRDY)==0);
|
||||
}
|
||||
break;
|
||||
case RCC_HSE:
|
||||
if (!(RCC->CR & RCC_CR_HSEON)) {
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
while ((RCC->CR & RCC_CR_HSERDY)==0);
|
||||
}
|
||||
break;
|
||||
case RCC_PLL:
|
||||
if (!(RCC->CR & RCC_CR_PLLON)) {
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
while ((RCC->CR & RCC_CR_PLLRDY)==0);
|
||||
}
|
||||
break;
|
||||
case RCC_LSI:
|
||||
if (!(RCC->CSR & RCC_CSR_LSION)) {
|
||||
RCC->CSR |= RCC_CSR_LSION;
|
||||
while ((RCC->CSR & RCC_CSR_LSIRDY)==0);
|
||||
}
|
||||
break;
|
||||
case RCC_LSE:
|
||||
if (!(RCC->BDCR & RCC_BDCR_LSEON)) {
|
||||
RCC->BDCR |= RCC_BDCR_LSEON;
|
||||
while ((RCC->BDCR & RCC_BDCR_LSERDY)==0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void rcc_osc_off(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_HSI:
|
||||
RCC->CR &= ~RCC_CR_HSION;
|
||||
break;
|
||||
case RCC_HSE:
|
||||
RCC->CR &= ~(RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON);
|
||||
break;
|
||||
case RCC_PLL:
|
||||
RCC->CR &= ~RCC_CR_PLLON;
|
||||
break;
|
||||
case RCC_LSI:
|
||||
RCC->CSR &= ~RCC_CSR_LSION;
|
||||
break;
|
||||
case RCC_LSE:
|
||||
RCC->BDCR &= ~RCC_BDCR_LSEON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void rcc_set_sysclk(enum rcc_osc osc)
|
||||
{
|
||||
RCC->CFGR = (RCC->CFGR & ~0x3) | (osc & 3);
|
||||
while (((RCC->CFGR & 0xC)>>2) != osc);
|
||||
}
|
||||
|
||||
void rcc_config_clock(uint32_t config, Clock_t *sysclks)
|
||||
{
|
||||
struct ClockConfig_t *clk;
|
||||
|
||||
if (config < CLOCK_CONFIG_END) {
|
||||
clk=&(_clock_config[config]);
|
||||
} else {
|
||||
clk=&(_clock_config[CLOCK_CONFIG_PERFORMANCE]);
|
||||
}
|
||||
|
||||
if (clk->type == RCC_HSE) { // HSE Clock
|
||||
rcc_osc_on(RCC_HSE);
|
||||
rcc_set_sysclk(RCC_HSE);
|
||||
rcc_osc_off(RCC_PLL);
|
||||
rcc_osc_off(RCC_HSI);
|
||||
|
||||
} else if (clk->type == RCC_PLL) {
|
||||
// enable PWR module clocking
|
||||
RCC->APB1ENR |= 1<<28;
|
||||
|
||||
if (clk->pll_src == RCC_HSE) { // HSE Clock src
|
||||
rcc_osc_on(RCC_HSE);
|
||||
} else { // Default: HSI Clock src
|
||||
rcc_osc_on(RCC_HSI);
|
||||
}
|
||||
|
||||
// configure prescalers for
|
||||
// AHB: AHBCLK > 25MHz
|
||||
// APB1: APB1CLK <= 36MHz
|
||||
// APB2: APB2CLK <= 72MHz
|
||||
RCC->CFGR = ( RCC->CFGR & ~((0x3F<<8) | (0xF<<4) | (0x3<<14)) ) |
|
||||
((clk->hpre & 0xF) << 4) |
|
||||
((clk->ppre1 & 0x7) << 8) |
|
||||
((clk->ppre2 & 0x7) << 11)|
|
||||
(clk->adcpre << 14);
|
||||
|
||||
// configure PLL
|
||||
RCC->CFGR &= !(0xF<<18);
|
||||
RCC->CFGR |= clk->pllmul<<18;
|
||||
|
||||
// enable PLL oscillator
|
||||
rcc_osc_on(RCC_PLL);
|
||||
|
||||
// set Flash timings
|
||||
FLASH->ACR &= !0x8;
|
||||
FLASH->ACR |= clk->flash_cfg;
|
||||
//TODO set buffer bits
|
||||
|
||||
// connect to PLL
|
||||
rcc_set_sysclk(RCC_PLL);
|
||||
|
||||
// stop unused clock
|
||||
if ((clk->pll_src == RCC_HSE) && (RCC->CR & RCC_CR_HSION))
|
||||
rcc_osc_off(RCC_HSI);
|
||||
else
|
||||
rcc_osc_off(RCC_HSE);
|
||||
|
||||
} else { // Default: HSI Clock
|
||||
rcc_osc_on(RCC_HSI);
|
||||
rcc_set_sysclk(RCC_HSI);
|
||||
rcc_osc_off(RCC_PLL);
|
||||
rcc_osc_off(RCC_HSE);
|
||||
}
|
||||
sysclks->ahb_freq = clk->ahb_freq;
|
||||
sysclks->apb1_freq = clk->apb1_freq;
|
||||
sysclks->apb2_freq = clk->apb2_freq;
|
||||
sysclks->apb1_timer_freq =
|
||||
clk->ppre1==RCC_CFGR_PPRE_DIV_NONE ? clk->apb1_freq : 2*clk->apb1_freq;
|
||||
sysclks->apb2_timer_freq =
|
||||
clk->ppre2==RCC_CFGR_PPRE_DIV_NONE ? clk->apb2_freq : 2*clk->apb2_freq;
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
#ifndef _RCC_H_
|
||||
#define _RCC_H_
|
||||
|
||||
#include "../target/stm32f103xb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _Clock_t {
|
||||
uint32_t ahb_freq;
|
||||
uint32_t apb1_freq;
|
||||
uint32_t apb1_timer_freq;
|
||||
uint32_t apb2_freq;
|
||||
uint32_t apb2_timer_freq;
|
||||
} Clock_t;
|
||||
|
||||
enum Clock_config {
|
||||
CLOCK_CONFIG_PERFORMANCE,
|
||||
CLOCK_CONFIG_POWERSAVE,
|
||||
CLOCK_CONFIG_END
|
||||
};
|
||||
|
||||
//void SystemInit(void);
|
||||
|
||||
void rcc_config_clock(uint32_t config, Clock_t *sysclks);
|
||||
|
||||
#
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,311 +0,0 @@
|
||||
#include "timer.h"
|
||||
|
||||
extern Clock_t sysclks;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static OnTick callback1 = 0;
|
||||
static OnTick callback2 = 0;
|
||||
static OnTick callback3 = 0;
|
||||
static OnTick callback4 = 0;
|
||||
|
||||
void TIM1_UP_IRQHandler(void) {
|
||||
if (callback1) callback1();
|
||||
TIM1->SR &= ~0x1F;
|
||||
}
|
||||
|
||||
void TIM2_IRQHandler(void) {
|
||||
if (callback2) callback2();
|
||||
TIM2->SR &= ~0x1F;
|
||||
}
|
||||
|
||||
void TIM3_IRQHandler(void) {
|
||||
if (callback3) callback3();
|
||||
TIM3->SR &= ~0x1F;
|
||||
}
|
||||
|
||||
void TIM4_IRQHandler(void) {
|
||||
if (callback4) callback4();
|
||||
TIM4->SR &= ~0x1F;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int timer_config_cb(TIM_TypeDef* tmr, uint32_t* clk, OnTick cb) {
|
||||
IRQn_Type irqn;
|
||||
uint32_t irq_priority;
|
||||
|
||||
// get clocks config
|
||||
if (tmr == TIM1) {
|
||||
*clk = sysclks.apb2_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback1 = cb;
|
||||
irqn = TIM1_UP_IRQn; //every update
|
||||
irq_priority = TIM1_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB2ENR |= 1<<11;
|
||||
|
||||
} else if (tmr == TIM2) {
|
||||
*clk = sysclks.apb1_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback2 = cb;
|
||||
irqn = TIM2_IRQn;
|
||||
irq_priority = TIM2_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB1ENR |= 1<<0;
|
||||
|
||||
} else if (tmr == TIM3) {
|
||||
*clk = sysclks.apb1_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback3 = cb;
|
||||
irqn = TIM3_IRQn;
|
||||
irq_priority = TIM3_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB1ENR |= 1<<1;
|
||||
|
||||
} else if (tmr == TIM4) {
|
||||
*clk = sysclks.apb1_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback4 = cb;
|
||||
irqn = TIM4_IRQn;
|
||||
irq_priority = TIM4_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB1ENR |= 1<<2;
|
||||
|
||||
} else return -1;
|
||||
|
||||
// clear pending interrupts
|
||||
tmr->SR &= !1;
|
||||
|
||||
// Enable interrupts
|
||||
tmr->DIER = (1<<0);
|
||||
NVIC_SetPriority(irqn,irq_priority);
|
||||
NVIC_EnableIRQ(irqn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int timer_wait_ms(TIM_TypeDef* tmr, uint16_t ms, OnTick cb) {
|
||||
uint32_t clk = 0;
|
||||
|
||||
if(!cb) { //blocking
|
||||
//get clocks config
|
||||
if (tmr == TIM1) {
|
||||
clk = sysclks.apb2_timer_freq;
|
||||
RCC->APB2ENR |= 1<<11;
|
||||
}
|
||||
else {
|
||||
clk = sysclks.apb1_timer_freq;
|
||||
if (tmr == TIM2) RCC->APB1ENR |= 1<<0;
|
||||
else if (tmr == TIM3) RCC->APB1ENR |= 1<<1;
|
||||
else if (tmr == TIM4) RCC->APB1ENR |= 1<<2;
|
||||
else return -1; // no such timer
|
||||
}
|
||||
|
||||
// set period
|
||||
tmr->ARR = 0xFFFFFFFF;
|
||||
|
||||
} else { //non-blocking
|
||||
if(timer_config_cb(tmr, &clk, cb)) return -1;
|
||||
|
||||
// set period
|
||||
tmr->ARR = ms-1;
|
||||
}
|
||||
|
||||
// set mode
|
||||
tmr->CR1 = (1<<7) | (1<<2); //buffering and update settings
|
||||
tmr->CR1 |= (1<<3); //one pulse mode
|
||||
|
||||
// set prescaler 1ms
|
||||
tmr->PSC = 8*(clk/1000)-1; //PSC = clk/f - 1 | don't know why 8 times..
|
||||
|
||||
timer_start(tmr);
|
||||
|
||||
if(!cb) {
|
||||
while(tmr->CNT < ms); //waiting for end of delay
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_wait_us(TIM_TypeDef* tmr, uint16_t us, OnTick cb) {
|
||||
uint32_t clk = 0;
|
||||
|
||||
if(!cb) { //blocking
|
||||
//get clocks config
|
||||
if (tmr == TIM1) {
|
||||
clk = sysclks.apb2_timer_freq;
|
||||
RCC->APB2ENR |= 1<<11;
|
||||
}
|
||||
else {
|
||||
clk = sysclks.apb1_timer_freq;
|
||||
if (tmr == TIM2) RCC->APB1ENR |= 1<<0;
|
||||
else if (tmr == TIM3) RCC->APB1ENR |= 1<<1;
|
||||
else if (tmr == TIM4) RCC->APB1ENR |= 1<<2;
|
||||
else return -1; // no such timer
|
||||
}
|
||||
|
||||
// set period
|
||||
tmr->ARR = 0xFFFFFFFF;
|
||||
|
||||
} else { //non-blocking
|
||||
if(timer_config_cb(tmr, &clk, cb)) return -1;
|
||||
|
||||
// set period
|
||||
tmr->ARR = us-1;
|
||||
}
|
||||
|
||||
// set mode
|
||||
tmr->CR1 = (1<<7) | (1<<2); //buffering and update settings
|
||||
tmr->CR1 |= (1<<3); //one pulse mode
|
||||
|
||||
// set prescaler 1us
|
||||
tmr->PSC = 8*(clk/1000000)-1; //PSC = clk/f - 1 | don't know why 8 times..
|
||||
|
||||
timer_start(tmr);
|
||||
|
||||
if(!cb) {
|
||||
while(tmr->CNT < us); //waiting for end of delay
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int timer_tick_init(TIM_TypeDef *tmr, uint16_t tick_ms, OnTick cb) {
|
||||
IRQn_Type irqn;
|
||||
uint32_t irq_priority, clk;
|
||||
|
||||
// get back the clock frequency
|
||||
if (tmr == TIM1) {
|
||||
clk = sysclks.apb2_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback1 = cb;
|
||||
irqn = TIM1_UP_IRQn; //every update
|
||||
irq_priority = TIM1_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB2ENR |= 1<<11;
|
||||
|
||||
} else if (tmr == TIM2) {
|
||||
clk = sysclks.apb1_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback2 = cb;
|
||||
irqn = TIM2_IRQn;
|
||||
irq_priority = TIM2_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB1ENR |= 1<<0;
|
||||
|
||||
} else if (tmr == TIM3) {
|
||||
clk = sysclks.apb1_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback3 = cb;
|
||||
irqn = TIM3_IRQn;
|
||||
irq_priority = TIM3_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB1ENR |= 1<<1;
|
||||
|
||||
} else if (tmr == TIM4) {
|
||||
clk = sysclks.apb1_timer_freq;
|
||||
|
||||
// register callback function
|
||||
callback4 = cb;
|
||||
irqn = TIM4_IRQn;
|
||||
irq_priority = TIM4_IRQ_PRIORITY;
|
||||
|
||||
// enable timer clocking
|
||||
RCC->APB1ENR |= 1<<2;
|
||||
|
||||
} else return -1;
|
||||
|
||||
// clear pending interrupts
|
||||
tmr->SR &= !1;
|
||||
|
||||
// set mode
|
||||
tmr->CR1 = (1<<7) | (1<<2); //buffering and update settings
|
||||
tmr->DIER = (1<<0); //Enable interrupts
|
||||
|
||||
// set prescaler 1ms
|
||||
tmr->PSC = 8*(clk/1000)-1; //PSC = clk/f - 1 | don't know why 8 times...
|
||||
|
||||
// set period
|
||||
if(timer_set_period(tmr,tick_ms)) return -1;
|
||||
|
||||
if (cb) {
|
||||
NVIC_SetPriority(irqn,irq_priority);
|
||||
NVIC_EnableIRQ(irqn); //unmask IRQ
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set_period(TIM_TypeDef *tmr, uint16_t tick) {
|
||||
// set period
|
||||
tmr->ARR = tick-1; //tickms = (ARR+1)Tpsc
|
||||
|
||||
// force update to reset counter and apply prescaler
|
||||
tmr->EGR |= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void timer_start(TIM_TypeDef *tmr) {
|
||||
// force update to reset counter and prescaler
|
||||
tmr->EGR |= 1;
|
||||
|
||||
// enable counting
|
||||
tmr->CR1 |= 1;
|
||||
}
|
||||
|
||||
void timer_stop(TIM_TypeDef *tmr) {
|
||||
// disable counting
|
||||
tmr->CR1 &= !1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int timer_enc_init(TIM_TypeDef* tmr) {
|
||||
// enable timer
|
||||
if (tmr == TIM1) {
|
||||
RCC->APB2ENR |= 1<<11;
|
||||
|
||||
} else if (tmr == TIM2) {
|
||||
RCC->APB1ENR |= 1<<0;
|
||||
|
||||
} else if (tmr == TIM3) {
|
||||
RCC->APB1ENR |= 1<<1;
|
||||
|
||||
} else if (tmr == TIM4) {
|
||||
RCC->APB1ENR |= 1<<2;
|
||||
|
||||
} else return -1; //no such timer
|
||||
|
||||
//TODO set registers at reset value
|
||||
|
||||
tmr->SMCR |= 0x1; //count on only one edge
|
||||
tmr->ARR = (1 << 16)-1;
|
||||
|
||||
// map inputs
|
||||
tmr->CCMR1 |= 0x9;
|
||||
tmr->CCMR1 |= 0x9 << 8;
|
||||
|
||||
// enable input channels and invert them //TODO add an otpion for that
|
||||
tmr->CCER |= 0x3;
|
||||
tmr->CCER |= 0x3 << 4;
|
||||
|
||||
tmr->CR1 |= 0x1; //enable timer
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#include "../target/stm32f103xb.h"
|
||||
#include "../config.h"
|
||||
#include "rcc.h"
|
||||
|
||||
typedef void (*OnTick)(void);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** timer_wait_ms
|
||||
* wait for ms milliseconds function
|
||||
*/
|
||||
int timer_wait_ms(TIM_TypeDef *tmr, uint16_t ms, OnTick cb);
|
||||
|
||||
/** timer_wait_us
|
||||
* wait for us microseconds function
|
||||
*/
|
||||
int timer_wait_us(TIM_TypeDef *tmr, uint16_t us, OnTick cb);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** timer_tick_init
|
||||
* setup timer to call cb function periodically, each tick_ms
|
||||
*/
|
||||
int timer_tick_init(TIM_TypeDef *tmr, uint16_t tick_ms, OnTick cb);
|
||||
|
||||
/** timer_set_period
|
||||
* change the period, in ms when called after tick_init,
|
||||
* otherwise in whatever unit the timer is configured
|
||||
* reset count when used
|
||||
*/
|
||||
int timer_set_period(TIM_TypeDef *tmr, uint16_t tick);
|
||||
|
||||
/** timer_start
|
||||
* reset count and start counting
|
||||
*/
|
||||
void timer_start(TIM_TypeDef *tmr);
|
||||
|
||||
/** timer_stop
|
||||
* stop counting
|
||||
*/
|
||||
void timer_stop(TIM_TypeDef *tmr);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** timer_enc_init
|
||||
* setup timer to read encoder output and keep track of it's position in the
|
||||
* CNT register whithout using CPU time
|
||||
*/
|
||||
int timer_enc_init(TIM_TypeDef* tmr);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//#define PWM_CHANNEL_1 0
|
||||
//#define PWM_CHANNEL_2 1
|
||||
//#define PWM_CHANNEL_3 2
|
||||
//#define PWM_CHANNEL_4 3
|
||||
//
|
||||
///** pwm_init
|
||||
// * setup pwm timer period, each tick_ms
|
||||
// */
|
||||
//int pwm_init(TIM_TypeDef *pwm, uint32_t period_ms, OnTick cb);
|
||||
//
|
||||
///** pwm_channel_enable
|
||||
// * set up pwm channel
|
||||
// */
|
||||
//int pwm_channel_enable(TIM_TypeDef *pwm, uint32_t channel, uint32_t dutycycle, uint32_t oe);
|
||||
//
|
||||
///** pwm_channel_disable
|
||||
// * disable pwm channel
|
||||
// */
|
||||
//int pwm_channel_disable(TIM_TypeDef *pwm, uint32_t channel);
|
||||
//
|
||||
///** pwm_channel_set
|
||||
// * set up dutycycle for pwm channel
|
||||
// */
|
||||
//int pwm_channel_set(TIM_TypeDef *pwm, uint32_t channel, uint32_t dutycycle);
|
||||
//
|
||||
///** pwm_start
|
||||
// * start counting
|
||||
// */
|
||||
//#define pwm_start(pwm) timer_start(pwm)
|
||||
//
|
||||
///** pwm_stop
|
||||
// * stop and reset counting
|
||||
// */
|
||||
//#define pwm_stop(pwm) timer_stop(pwm)
|
||||
|
||||
#endif
|
||||
|
||||
52
src/main.c
52
src/main.c
@ -1,52 +0,0 @@
|
||||
// standard headers
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// driver includes
|
||||
#include "drivers/rcc.h"
|
||||
#include "drivers/io.h"
|
||||
|
||||
Clock_t sysclks;
|
||||
#include "drivers/timer.h"
|
||||
|
||||
extern uint32_t end;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* static variables */;
|
||||
int val = 0; //debug led
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* Timer IRQ */
|
||||
static void timeout_cb(void) {
|
||||
io_write(GPIOC, val, PIN_13);
|
||||
val = !val;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* main function */
|
||||
int main(void) {
|
||||
|
||||
// configure clocks (necessary before using timers)
|
||||
rcc_config_clock(CLOCK_CONFIG_PERFORMANCE, &sysclks);
|
||||
|
||||
// configure GPIO for LED
|
||||
if(io_configure(GPIOC, PIN_13, IO_MODE_OUTPUT | IO_OUT_PUSH_PULL, 0))
|
||||
return -1;
|
||||
io_write(GPIOC, 1, PIN_13);
|
||||
|
||||
// start timed interruption
|
||||
timer_tick_init(TIM2, 1000, timeout_cb);
|
||||
timer_start(TIM2);
|
||||
|
||||
uint32_t test = (uint32_t)(&end);
|
||||
test++;
|
||||
int* tab = (int*)malloc(10*sizeof(int));
|
||||
for(int i=0; i<10; ++i) {
|
||||
tab[i] = i;
|
||||
}
|
||||
|
||||
// main loop
|
||||
for(;;);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,177 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file LinkerScript.ld
|
||||
* @author Auto-generated by STM32CubeIDE
|
||||
* @brief Linker script for STM32F103C8Tx Device from STM32F1 series
|
||||
* 64Kbytes FLASH
|
||||
* 20Kbytes RAM
|
||||
*
|
||||
* Set heap size, stack size and stack location according
|
||||
* to application requirements.
|
||||
*
|
||||
* Set memory bank area and size if external memory is used
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
|
||||
|
||||
_Min_Heap_Size = 0x200; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||
|
||||
/* Memories definition */
|
||||
MEMORY
|
||||
{
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code into "FLASH" Rom type memory */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* The program code and other data into "FLASH" Rom type memory */
|
||||
.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 into "FLASH" Rom type memory */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab : {
|
||||
. = ALIGN(4);
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM : {
|
||||
. = ALIGN(4);
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.init_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* Used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections into "RAM" Ram type memory */
|
||||
.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
|
||||
|
||||
/* Uninitialized data section into "RAM" Ram type memory */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss section */
|
||||
_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" Ram type
|
||||
* memory left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} >RAM
|
||||
|
||||
/* Remove information from the compiler libraries */
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
|
||||
@ -1,371 +0,0 @@
|
||||
/**
|
||||
*************** (C) COPYRIGHT 2016 STMicroelectronics ************************
|
||||
* @file startup_stm32f103xb.s
|
||||
* @author MCD Application Team
|
||||
* @version V4.1.0
|
||||
* @date 29-April-2016
|
||||
* @brief STM32F103xB Devices vector table for Atollic toolchain.
|
||||
* This module performs:
|
||||
* - Set the initial SP
|
||||
* - Set the initial PC == Reset_Handler,
|
||||
* - Set the vector table entries with the exceptions ISR address
|
||||
* - Configure the clock system
|
||||
* - Branches to main in the C library (which eventually
|
||||
* calls main()).
|
||||
* After Reset the Cortex-M3 processor is in Thread mode,
|
||||
* priority is Privileged, and the Stack is set to Main.
|
||||
******************************************************************************
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 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-m3
|
||||
.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
|
||||
|
||||
.equ BootRAM, 0xF108F85F
|
||||
/**
|
||||
* @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 r0, =_estack
|
||||
mov sp, r0 /* 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
|
||||
|
||||
/* Call the clock system intitialization function.*/
|
||||
// bl SystemInit
|
||||
/* Call static constructors */
|
||||
//bl __libc_init_array
|
||||
/* Call the application's entry point.*/
|
||||
bl main
|
||||
//bl _start
|
||||
|
||||
LoopForever:
|
||||
b LoopForever
|
||||
|
||||
|
||||
.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
|
||||
.word WWDG_IRQHandler
|
||||
.word PVD_IRQHandler
|
||||
.word TAMPER_IRQHandler
|
||||
.word RTC_IRQHandler
|
||||
.word FLASH_IRQHandler
|
||||
.word RCC_IRQHandler
|
||||
.word EXTI0_IRQHandler
|
||||
.word EXTI1_IRQHandler
|
||||
.word EXTI2_IRQHandler
|
||||
.word EXTI3_IRQHandler
|
||||
.word EXTI4_IRQHandler
|
||||
.word DMA1_Channel1_IRQHandler
|
||||
.word DMA1_Channel2_IRQHandler
|
||||
.word DMA1_Channel3_IRQHandler
|
||||
.word DMA1_Channel4_IRQHandler
|
||||
.word DMA1_Channel5_IRQHandler
|
||||
.word DMA1_Channel6_IRQHandler
|
||||
.word DMA1_Channel7_IRQHandler
|
||||
.word ADC1_2_IRQHandler
|
||||
.word USB_HP_CAN1_TX_IRQHandler
|
||||
.word USB_LP_CAN1_RX0_IRQHandler
|
||||
.word CAN1_RX1_IRQHandler
|
||||
.word CAN1_SCE_IRQHandler
|
||||
.word EXTI9_5_IRQHandler
|
||||
.word TIM1_BRK_IRQHandler
|
||||
.word TIM1_UP_IRQHandler
|
||||
.word TIM1_TRG_COM_IRQHandler
|
||||
.word TIM1_CC_IRQHandler
|
||||
.word TIM2_IRQHandler
|
||||
.word TIM3_IRQHandler
|
||||
.word TIM4_IRQHandler
|
||||
.word I2C1_EV_IRQHandler
|
||||
.word I2C1_ER_IRQHandler
|
||||
.word I2C2_EV_IRQHandler
|
||||
.word I2C2_ER_IRQHandler
|
||||
.word SPI1_IRQHandler
|
||||
.word SPI2_IRQHandler
|
||||
.word USART1_IRQHandler
|
||||
.word USART2_IRQHandler
|
||||
.word USART3_IRQHandler
|
||||
.word EXTI15_10_IRQHandler
|
||||
.word RTC_Alarm_IRQHandler
|
||||
.word USBWakeUp_IRQHandler
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word BootRAM /* @0x108. This is for boot in RAM mode for
|
||||
STM32F10x Medium Density devices. */
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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 TAMPER_IRQHandler
|
||||
.thumb_set TAMPER_IRQHandler,Default_Handler
|
||||
|
||||
.weak RTC_IRQHandler
|
||||
.thumb_set RTC_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_Channel1_IRQHandler
|
||||
.thumb_set DMA1_Channel1_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Channel2_IRQHandler
|
||||
.thumb_set DMA1_Channel2_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Channel3_IRQHandler
|
||||
.thumb_set DMA1_Channel3_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Channel4_IRQHandler
|
||||
.thumb_set DMA1_Channel4_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Channel5_IRQHandler
|
||||
.thumb_set DMA1_Channel5_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Channel6_IRQHandler
|
||||
.thumb_set DMA1_Channel6_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Channel7_IRQHandler
|
||||
.thumb_set DMA1_Channel7_IRQHandler,Default_Handler
|
||||
|
||||
.weak ADC1_2_IRQHandler
|
||||
.thumb_set ADC1_2_IRQHandler,Default_Handler
|
||||
|
||||
.weak USB_HP_CAN1_TX_IRQHandler
|
||||
.thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler
|
||||
|
||||
.weak USB_LP_CAN1_RX0_IRQHandler
|
||||
.thumb_set USB_LP_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_IRQHandler
|
||||
.thumb_set TIM1_BRK_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_UP_IRQHandler
|
||||
.thumb_set TIM1_UP_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_TRG_COM_IRQHandler
|
||||
.thumb_set TIM1_TRG_COM_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 USBWakeUp_IRQHandler
|
||||
.thumb_set USBWakeUp_IRQHandler,Default_Handler
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
10642
src/target/stm32f103xb.h
10642
src/target/stm32f103xb.h
File diff suppressed because it is too large
Load Diff
@ -1,238 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.2.0
|
||||
* @date 31-March-2017
|
||||
* @brief CMSIS STM32F1xx Device Peripheral Access Layer Header File.
|
||||
*
|
||||
* The file is the unique include file that the application programmer
|
||||
* is using in the C source code, usually in main.c. This file contains:
|
||||
* - Configuration section that allows to select:
|
||||
* - The STM32F1xx device used in the target application
|
||||
* - To use or not the peripheral’s drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral’s registers
|
||||
* rather than drivers API), this option is controlled by
|
||||
* "#define USE_HAL_DRIVER"
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 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 stm32f1xx
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __STM32F1XX_H
|
||||
#define __STM32F1XX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** @addtogroup Library_configuration_section
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief STM32 Family
|
||||
*/
|
||||
#if !defined (STM32F1)
|
||||
#define STM32F1
|
||||
#endif /* STM32F1 */
|
||||
|
||||
/* Uncomment the line below according to the target STM32L device used in your
|
||||
application
|
||||
*/
|
||||
|
||||
#if !defined (STM32F100xB) && !defined (STM32F100xE) && !defined (STM32F101x6) && \
|
||||
!defined (STM32F101xB) && !defined (STM32F101xE) && !defined (STM32F101xG) && !defined (STM32F102x6) && !defined (STM32F102xB) && !defined (STM32F103x6) && \
|
||||
!defined (STM32F103xB) && !defined (STM32F103xE) && !defined (STM32F103xG) && !defined (STM32F105xC) && !defined (STM32F107xC)
|
||||
/* #define STM32F100xB */ /*!< STM32F100C4, STM32F100R4, STM32F100C6, STM32F100R6, STM32F100C8, STM32F100R8, STM32F100V8, STM32F100CB, STM32F100RB and STM32F100VB */
|
||||
/* #define STM32F100xE */ /*!< STM32F100RC, STM32F100VC, STM32F100ZC, STM32F100RD, STM32F100VD, STM32F100ZD, STM32F100RE, STM32F100VE and STM32F100ZE */
|
||||
/* #define STM32F101x6 */ /*!< STM32F101C4, STM32F101R4, STM32F101T4, STM32F101C6, STM32F101R6 and STM32F101T6 Devices */
|
||||
/* #define STM32F101xB */ /*!< STM32F101C8, STM32F101R8, STM32F101T8, STM32F101V8, STM32F101CB, STM32F101RB, STM32F101TB and STM32F101VB */
|
||||
/* #define STM32F101xE */ /*!< STM32F101RC, STM32F101VC, STM32F101ZC, STM32F101RD, STM32F101VD, STM32F101ZD, STM32F101RE, STM32F101VE and STM32F101ZE */
|
||||
/* #define STM32F101xG */ /*!< STM32F101RF, STM32F101VF, STM32F101ZF, STM32F101RG, STM32F101VG and STM32F101ZG */
|
||||
/* #define STM32F102x6 */ /*!< STM32F102C4, STM32F102R4, STM32F102C6 and STM32F102R6 */
|
||||
/* #define STM32F102xB */ /*!< STM32F102C8, STM32F102R8, STM32F102CB and STM32F102RB */
|
||||
/* #define STM32F103x6 */ /*!< STM32F103C4, STM32F103R4, STM32F103T4, STM32F103C6, STM32F103R6 and STM32F103T6 */
|
||||
#define STM32F103xB /*!< STM32F103C8, STM32F103R8, STM32F103T8, STM32F103V8, STM32F103CB, STM32F103RB, STM32F103TB and STM32F103VB */
|
||||
/* #define STM32F103xE */ /*!< STM32F103RC, STM32F103VC, STM32F103ZC, STM32F103RD, STM32F103VD, STM32F103ZD, STM32F103RE, STM32F103VE and STM32F103ZE */
|
||||
/* #define STM32F103xG */ /*!< STM32F103RF, STM32F103VF, STM32F103ZF, STM32F103RG, STM32F103VG and STM32F103ZG */
|
||||
/* #define STM32F105xC */ /*!< STM32F105R8, STM32F105V8, STM32F105RB, STM32F105VB, STM32F105RC and STM32F105VC */
|
||||
/* #define STM32F107xC */ /*!< STM32F107RB, STM32F107VB, STM32F107RC and STM32F107VC */
|
||||
#endif
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to switch between these
|
||||
devices, you can define the device in your toolchain compiler preprocessor.
|
||||
*/
|
||||
|
||||
#if !defined (USE_HAL_DRIVER)
|
||||
/**
|
||||
* @brief Comment the line below if you will not use the peripherals drivers.
|
||||
In this case, these drivers will not be included and the application code will
|
||||
be based on direct access to peripherals registers
|
||||
*/
|
||||
//#define USE_HAL_DRIVER
|
||||
#endif /* USE_HAL_DRIVER */
|
||||
|
||||
/**
|
||||
* @brief CMSIS Device version number V4.2.0
|
||||
*/
|
||||
#define __STM32F1_CMSIS_VERSION_MAIN (0x04) /*!< [31:24] main version */
|
||||
#define __STM32F1_CMSIS_VERSION_SUB1 (0x02) /*!< [23:16] sub1 version */
|
||||
#define __STM32F1_CMSIS_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */
|
||||
#define __STM32F1_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */
|
||||
#define __STM32F1_CMSIS_VERSION ((__STM32F1_CMSIS_VERSION_MAIN << 24)\
|
||||
|(__STM32F1_CMSIS_VERSION_SUB1 << 16)\
|
||||
|(__STM32F1_CMSIS_VERSION_SUB2 << 8 )\
|
||||
|(__STM32F1_CMSIS_VERSION_RC))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Device_Included
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(STM32F100xB)
|
||||
#include "stm32f100xb.h"
|
||||
#elif defined(STM32F100xE)
|
||||
#include "stm32f100xe.h"
|
||||
#elif defined(STM32F101x6)
|
||||
#include "stm32f101x6.h"
|
||||
#elif defined(STM32F101xB)
|
||||
#include "stm32f101xb.h"
|
||||
#elif defined(STM32F101xE)
|
||||
#include "stm32f101xe.h"
|
||||
#elif defined(STM32F101xG)
|
||||
#include "stm32f101xg.h"
|
||||
#elif defined(STM32F102x6)
|
||||
#include "stm32f102x6.h"
|
||||
#elif defined(STM32F102xB)
|
||||
#include "stm32f102xb.h"
|
||||
#elif defined(STM32F103x6)
|
||||
#include "stm32f103x6.h"
|
||||
#elif defined(STM32F103xB)
|
||||
#include "stm32f103xb.h"
|
||||
#elif defined(STM32F103xE)
|
||||
#include "stm32f103xe.h"
|
||||
#elif defined(STM32F103xG)
|
||||
#include "stm32f103xg.h"
|
||||
#elif defined(STM32F105xC)
|
||||
#include "stm32f105xc.h"
|
||||
#elif defined(STM32F107xC)
|
||||
#include "stm32f107xc.h"
|
||||
#else
|
||||
#error "Please select first the target STM32F1xx device used in your application (in stm32f1xx.h file)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Exported_types
|
||||
* @{
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
RESET = 0,
|
||||
SET = !RESET
|
||||
} FlagStatus, ITStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DISABLE = 0,
|
||||
ENABLE = !DISABLE
|
||||
} FunctionalState;
|
||||
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ERROR = 0,
|
||||
SUCCESS = !ERROR
|
||||
} ErrorStatus;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Exported_macros
|
||||
* @{
|
||||
*/
|
||||
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
|
||||
|
||||
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
|
||||
|
||||
#define READ_BIT(REG, BIT) ((REG) & (BIT))
|
||||
|
||||
#define CLEAR_REG(REG) ((REG) = (0x0))
|
||||
|
||||
#define WRITE_REG(REG, VAL) ((REG) = (VAL))
|
||||
|
||||
#define READ_REG(REG) ((REG))
|
||||
|
||||
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
|
||||
|
||||
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined (USE_HAL_DRIVER)
|
||||
#include "stm32f1xx_hal.h"
|
||||
#endif /* USE_HAL_DRIVER */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __STM32F1xx_H */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@ -1,109 +0,0 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file configures the system clock as follows:
|
||||
*-----------------------------------------------------------------------------
|
||||
* System clock source | 1- PLL_HSE_EXTC | 3- PLL_HSI
|
||||
* | (external 8 MHz clock) | (internal 8 MHz)
|
||||
* | 2- PLL_HSE_XTAL |
|
||||
* | (external 8 MHz xtal) |
|
||||
*-----------------------------------------------------------------------------
|
||||
* SYSCLK(MHz) | 72 | 64
|
||||
*-----------------------------------------------------------------------------
|
||||
* AHBCLK (MHz) | 72 | 64
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB1CLK (MHz) | 36 | 32
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB2CLK (MHz) | 72 | 64
|
||||
*-----------------------------------------------------------------------------
|
||||
* USB capable (48 MHz precise clock) | NO | NO
|
||||
*-----------------------------------------------------------------------------
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "stm32f1xx.h"
|
||||
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table in
|
||||
Internal SRAM. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system
|
||||
* Initialize the Embedded Flash Interface, the PLL and update the
|
||||
* SystemCoreClock variable.
|
||||
* @note This function should be used only after reset.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
|
||||
/* Set HSION bit */
|
||||
RCC->CR |= 0x00000001U;
|
||||
|
||||
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
|
||||
#if !defined(STM32F105xC) && !defined(STM32F107xC)
|
||||
RCC->CFGR &= 0xF8FF0000U;
|
||||
#else
|
||||
RCC->CFGR &= 0xF0FF0000U;
|
||||
#endif /* STM32F105xC */
|
||||
|
||||
/* Reset HSEON, CSSON and PLLON bits */
|
||||
RCC->CR &= 0xFEF6FFFFU;
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC->CR &= 0xFFFBFFFFU;
|
||||
|
||||
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
|
||||
RCC->CFGR &= 0xFF80FFFFU;
|
||||
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/* Reset PLL2ON and PLL3ON bits */
|
||||
RCC->CR &= 0xEBFFFFFFU;
|
||||
|
||||
/* Disable all interrupts and clear pending bits */
|
||||
RCC->CIR = 0x00FF0000U;
|
||||
|
||||
/* Reset CFGR2 register */
|
||||
RCC->CFGR2 = 0x00000000U;
|
||||
#elif defined(STM32F100xB) || defined(STM32F100xE)
|
||||
/* Disable all interrupts and clear pending bits */
|
||||
RCC->CIR = 0x009F0000U;
|
||||
|
||||
/* Reset CFGR2 register */
|
||||
RCC->CFGR2 = 0x00000000U;
|
||||
#else
|
||||
/* Disable all interrupts and clear pending bits */
|
||||
RCC->CIR = 0x009F0000U;
|
||||
#endif /* STM32F105xC */
|
||||
|
||||
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
|
||||
#ifdef DATA_IN_ExtSRAM
|
||||
SystemInit_ExtMemCtl();
|
||||
#endif /* DATA_IN_ExtSRAM */
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
}
|
||||
|
||||
@ -1,118 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32f10x.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.2.0
|
||||
* @date 31-March-2017
|
||||
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 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 stm32f10x_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define to prevent recursive inclusion
|
||||
*/
|
||||
#ifndef __SYSTEM_STM32F10X_H
|
||||
#define __SYSTEM_STM32F10X_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F10x_System_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_types
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
extern const uint8_t AHBPrescTable[16U]; /*!< AHB prescalers table values */
|
||||
extern const uint8_t APBPrescTable[8U]; /*!< APB prescalers table values */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
extern void SetSysClock(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SYSTEM_STM32F10X_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
82
srv/debug.c
Normal file
82
srv/debug.c
Normal file
@ -0,0 +1,82 @@
|
||||
/** @file debug.c
|
||||
* Module handling various debug functions
|
||||
*
|
||||
* The module provides a range of functions and tools to make debug more
|
||||
* convenient
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "debug.h"
|
||||
#include "dma_mbuf.h"
|
||||
#include "format.h"
|
||||
|
||||
#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static uint32_t write_debug(uint8_t c, void* arg);
|
||||
|
||||
#define BUFFER_SIZE 162 //(80 char line + \n) * 2
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static struct DmaMultiBuffer mbuf;
|
||||
static uint8_t tx_buffer[BUFFER_SIZE];
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port,
|
||||
enum GpioPin tx_pin)
|
||||
{
|
||||
gpio_configure(tx_port, tx_pin, GPIO_MODE_OUTPUT_FAST,
|
||||
GPIO_CONFIG_OUT_ALT_PUSH_PULL);
|
||||
usart_configure(usart, USART_CONFIG_8N1, 1000000);
|
||||
dma_mbuf_configure(&mbuf,usart_configure_tx_dma(usart),
|
||||
DMA_CONFIG_PRIO_LOW, tx_buffer, BUFFER_SIZE);
|
||||
|
||||
debug_trace("\n");
|
||||
debug_trace("------------------------------------------------------------------------------\n");
|
||||
debug_trace("starting debug software\n");
|
||||
debug_trace("compiled on " __DATE__ " at " __TIME__ "\n");
|
||||
debug_trace("------------------------------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
void _debug_print(const char* restrict header,
|
||||
const char* restrict format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
format_vfctprintf(write_debug, nullptr, header, va);
|
||||
format_vfctprintf(write_debug, nullptr, format, va);
|
||||
va_end(va);
|
||||
write_debug('\n', nullptr);
|
||||
|
||||
//ensure everything is written when done
|
||||
while (dma_mbuf_switch(&mbuf)) {}
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Callback to use with format_vfctprintf() to print caracters to the debug port
|
||||
*/
|
||||
static uint32_t write_debug(uint8_t c, void* arg)
|
||||
{
|
||||
(void)arg; //unused, required because of FormatCallback
|
||||
|
||||
while (dma_mbuf_write_byte(&mbuf, c))
|
||||
{
|
||||
//buffer is full, wait until transfer started
|
||||
while (dma_mbuf_switch(&mbuf)) {}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif //DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR
|
||||
|
||||
97
srv/debug.h
Normal file
97
srv/debug.h
Normal file
@ -0,0 +1,97 @@
|
||||
/** @file debug.h
|
||||
* Module handling various debug functions
|
||||
*
|
||||
* The module provides a range of functions and tools to make debug more
|
||||
* convenient
|
||||
*/
|
||||
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "../drv/usart.h"
|
||||
#include "../drv/gpio.h"
|
||||
|
||||
#define DEBUG_TRACE 1
|
||||
#define DEBUG_WARN 1
|
||||
#define DEBUG_ERROR 1
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR
|
||||
#define debug_init(usart, tx_port, tx_pin) _debug_init(usart, tx_port, tx_pin)
|
||||
#else
|
||||
#define debug_init(usart) do {} while (0)
|
||||
#endif
|
||||
|
||||
#if DEBUG_TRACE
|
||||
/**
|
||||
* Prints a trace message on the debug port. This function should return
|
||||
* immediately, provided that the message's length doesn't exceed 80 caracters
|
||||
* and that it isn't called in very quick succession. Otherwise, it will block
|
||||
* until the internal buffering system is ready to accept the message
|
||||
*/
|
||||
#define debug_trace(format, ...) _debug_print("T:", \
|
||||
format __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define debug_trace(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#if DEBUG_WARN
|
||||
/**
|
||||
* Prints a warning message on the debug port. This function should return
|
||||
* immediately, provided that the message's length doesn't exceed 80 caracters
|
||||
* and that it isn't called in very quick succession. Otherwise, it will block
|
||||
* until the internal buffering system is ready to accept the message
|
||||
*/
|
||||
#define debug_warn(format, ...) _debug_print("W:", \
|
||||
format __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define debug_warn(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#if DEBUG_ERROR
|
||||
/**
|
||||
* Prints an error message on the debug port. This function should return
|
||||
* immediately, provided that the message's length doesn't exceed 80 caracters
|
||||
* and that it isn't called in very quick succession. Otherwise, it will block
|
||||
* until the internal buffering system is ready to accept the message
|
||||
*/
|
||||
#define debug_error(format, ...) _debug_print("E:", \
|
||||
format __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define debug_error(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR
|
||||
|
||||
/**
|
||||
* Initializes the debug system to use the given usart peripheral on the given
|
||||
* tx port, printing a banner if traces are enabled.
|
||||
* The usart doesn't need to be configured, neither does the tx port.
|
||||
*
|
||||
* This function shouldn't be called directly. Instead, use the debug_init macro
|
||||
*/
|
||||
void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port,
|
||||
enum GpioPin tx_pin);
|
||||
|
||||
/**
|
||||
* Prints a debug message on the debug port with the given header. This function
|
||||
* should return immediately, provided that the message's length doesn't exceed
|
||||
* 80 caracters and that it isn't called in very quick succession. Otherwise, it
|
||||
* will block until the internal buffering system is ready to accept the message
|
||||
*
|
||||
* This function shouldn't be called directly. Instead, use the debug macros
|
||||
*/
|
||||
void _debug_print(const char* restrict header,
|
||||
const char* restrict format, ...);
|
||||
|
||||
#endif
|
||||
|
||||
#endif //_DEBUG_H_
|
||||
|
||||
100
srv/dma_cbuf.c
Normal file
100
srv/dma_cbuf.c
Normal file
@ -0,0 +1,100 @@
|
||||
/** @file dma_cbuf.c
|
||||
* Module handling Direct Memory Access controller's circular system
|
||||
*
|
||||
* The module provides a convenient tool to receive data from a peripheral in a
|
||||
* buffered, low-latency, low-cpu usage, non-blocking way
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "dma_cbuf.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* DMA configuration to be used for the buffer. Additionnal configuration may be
|
||||
* added by the peripherals used
|
||||
*/
|
||||
#define DMA_CONFIG (DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_PERIPH \
|
||||
| DMA_CONFIG_CIRCULAR | DMA_CONFIG_INC_MEM \
|
||||
| DMA_CONFIG_MSIZE_8BITS)
|
||||
|
||||
static void cbuf_callback(enum DmaIRQSource src, volatile void* param);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void dma_cbuf_configure(volatile struct DmaCircBuffer* buffer,
|
||||
const struct DmaParam* param, enum DmaConfig priority,
|
||||
volatile void* raw_buffer, uint16_t buffer_size)
|
||||
{
|
||||
error_assert(buffer != nullptr);
|
||||
error_assert(param != nullptr);
|
||||
error_assert(raw_buffer != nullptr);
|
||||
|
||||
buffer->buffer = raw_buffer;
|
||||
|
||||
buffer->size = buffer_size;
|
||||
buffer->begin = 0;
|
||||
|
||||
buffer->dma = param->dma;
|
||||
buffer->channel = param->channel;
|
||||
|
||||
buffer->dma_looped = false;
|
||||
|
||||
dma_configure(buffer->dma, buffer->channel,
|
||||
DMA_CONFIG | param->config | priority,
|
||||
param->periph, cbuf_callback, buffer);
|
||||
dma_start(buffer->dma, buffer->channel, buffer->buffer, buffer->size);
|
||||
}
|
||||
|
||||
uint32_t dma_cbuf_read_byte(volatile struct DmaCircBuffer* buffer,
|
||||
uint8_t* byte)
|
||||
{
|
||||
error_assert(buffer != nullptr);
|
||||
error_assert(byte != nullptr);
|
||||
|
||||
//retreive the current end of the buffer based on the DMA's progress
|
||||
uint16_t end = buffer->size
|
||||
- dma_get_remaining(buffer->dma, buffer->channel);
|
||||
|
||||
//check for bytes to read and overflow
|
||||
if ((end > buffer->begin) && buffer->dma_looped) {
|
||||
//TODO overflow
|
||||
buffer->begin = end;
|
||||
} else if ((buffer->begin == end) && !buffer->dma_looped) {
|
||||
//TODO no data
|
||||
return 1;
|
||||
}
|
||||
|
||||
//read the oldest byte and advance the buffer
|
||||
uint8_t* raw_buffer = (uint8_t*)buffer->buffer;
|
||||
*byte = raw_buffer[buffer->begin];
|
||||
++buffer->begin;
|
||||
if (buffer->begin >= buffer->size) {
|
||||
buffer->begin = 0;
|
||||
buffer->dma_looped = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Callback called on DMA RX tranfert's completion. Sets a flag needed to
|
||||
* properly handle the circular buffer
|
||||
*/
|
||||
static void cbuf_callback(enum DmaIRQSource src, volatile void* param)
|
||||
{
|
||||
(void)src; //only transfer complete expected
|
||||
error_assert(param != nullptr);
|
||||
|
||||
volatile struct DmaCircBuffer* buffer = param;
|
||||
buffer->dma_looped = true;
|
||||
}
|
||||
|
||||
64
srv/dma_cbuf.h
Normal file
64
srv/dma_cbuf.h
Normal file
@ -0,0 +1,64 @@
|
||||
/** @file dma_cbuf.h
|
||||
* Module handling Direct Memory Access controller's circular system
|
||||
*
|
||||
* The module provides a convenient tool to receive data from a peripheral in a
|
||||
* buffered, low-latency, low-cpu usage, non-blocking way
|
||||
*/
|
||||
|
||||
#ifndef _DMA_CBUF_H_
|
||||
#define _DMA_CBUF_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "../drv/dma.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Struct used by the circular buffer system. This system allows bufferized
|
||||
* reads to a peripheral with no latency, minimal cpu usage and customisable
|
||||
* buffer sizes
|
||||
*/
|
||||
struct DmaCircBuffer {
|
||||
volatile void* buffer; //the buffer to use as a circular buffer
|
||||
|
||||
uint16_t size; //the size of the buffer
|
||||
uint16_t begin; //pointer to the current begin of the buffer
|
||||
|
||||
enum DmaPeriph dma; //DMA peripheral used for transfers
|
||||
enum DmaChannel channel; //DMA channel used for transfers
|
||||
|
||||
bool dma_looped; //whether the DMA looped or not (buffer overflow)
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configure a DMA circular buffer for a single DMA channel. A standard buffer
|
||||
* is used a base to construct a circular buffer, supplied in data by DMA
|
||||
* tranfers from a peripheral.
|
||||
* The peripheral's specific configuration must be handled separately.
|
||||
* Each peripheral's driver is responsible for providing the DMA configuration
|
||||
* for said peripheral, though it can be manually given too. Please note that
|
||||
* multiple peripherals may share the same DMA channel, which will cause issue
|
||||
* when used with this buffer.
|
||||
*
|
||||
* Once this function is called, the system will start running right away and
|
||||
* will stay running until manually stopped
|
||||
*/
|
||||
void dma_cbuf_configure(volatile struct DmaCircBuffer* buffer,
|
||||
const struct DmaParam* param, enum DmaConfig priority,
|
||||
volatile void* raw_buffer, uint16_t buffer_size);
|
||||
|
||||
/**
|
||||
* Reads a bytes from the buffer, returning if the read operation was
|
||||
* successfull, 1 otherwise. This function is non-blocking.
|
||||
*/
|
||||
uint32_t dma_cbuf_read_byte(volatile struct DmaCircBuffer* buffer,
|
||||
uint8_t* byte);
|
||||
|
||||
|
||||
#endif //_DMA_CBUF_H_
|
||||
|
||||
116
srv/dma_mbuf.c
Normal file
116
srv/dma_mbuf.c
Normal file
@ -0,0 +1,116 @@
|
||||
/** @file dma_mbuf.h
|
||||
* Module handling Direct Memory Access controller's multibuffer system
|
||||
*
|
||||
* The module provides a convenient tool to send data to a peripheral in a
|
||||
* buffered, low-altency, low-cpu usage, non-blocking way
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "dma_mbuf.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* DMA configuration to be used for the buffer. Additionnal configuration may be
|
||||
* added by the peripherals used
|
||||
*/
|
||||
#define DMA_CONFIG (DMA_CONFIG_IRQ_COMPLETE | DMA_CONFIG_FROM_MEM \
|
||||
| DMA_CONFIG_INC_MEM | DMA_CONFIG_MSIZE_8BITS)
|
||||
|
||||
static void mbuf_callback(enum DmaIRQSource src, volatile void* param);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer,
|
||||
const struct DmaParam* param, enum DmaConfig priority,
|
||||
void* raw_buffer, uint16_t buffer_size)
|
||||
{
|
||||
error_assert(buffer != nullptr);
|
||||
error_assert(param != nullptr);
|
||||
error_assert(raw_buffer != nullptr);
|
||||
|
||||
buffer->raw_buffer = raw_buffer;
|
||||
|
||||
buffer->buffer_size = buffer_size / 2;
|
||||
|
||||
buffer->byte_index = 0;
|
||||
buffer->buffer_index = 0;
|
||||
buffer->dma = param->dma;
|
||||
buffer->channel = param->channel;
|
||||
|
||||
buffer->dma_running = false;
|
||||
|
||||
dma_configure(buffer->dma, buffer->channel,
|
||||
DMA_CONFIG | param->config | priority,
|
||||
param->periph, mbuf_callback, buffer);
|
||||
}
|
||||
|
||||
uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer,
|
||||
uint8_t byte)
|
||||
{
|
||||
error_assert(buffer != nullptr);
|
||||
|
||||
//if the current buffer is full, give up
|
||||
if (buffer->byte_index >= buffer->buffer_size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//write the byte
|
||||
buffer->raw_buffer[buffer->buffer_index * buffer->buffer_size
|
||||
+ buffer->byte_index] = byte;
|
||||
++buffer->byte_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer)
|
||||
{
|
||||
error_assert(buffer != nullptr);
|
||||
|
||||
//no data to send, stop here
|
||||
if (buffer->byte_index == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//dma already running, give up
|
||||
if (buffer->dma_running) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//start a new transfer
|
||||
buffer->dma_running = true;
|
||||
dma_start(buffer->dma, buffer->channel,
|
||||
&buffer->raw_buffer[buffer->buffer_index * buffer->buffer_size],
|
||||
buffer->byte_index);
|
||||
|
||||
buffer->byte_index = 0;
|
||||
++buffer->buffer_index;
|
||||
if (buffer->buffer_index > 1) {
|
||||
buffer->buffer_index = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Callback called on DMA TX tranfert's completion. Stops the DMA and notifies
|
||||
* the buffer that the transfer is done.
|
||||
*/
|
||||
static void mbuf_callback(enum DmaIRQSource src, volatile void* param)
|
||||
{
|
||||
(void)src; //only transfer complete expected
|
||||
error_assert(param != nullptr);
|
||||
|
||||
volatile struct DmaMultiBuffer* buffer = param;
|
||||
dma_stop(buffer->dma, buffer->channel);
|
||||
buffer->dma_running = false;
|
||||
}
|
||||
|
||||
76
srv/dma_mbuf.h
Normal file
76
srv/dma_mbuf.h
Normal file
@ -0,0 +1,76 @@
|
||||
/** @file dma_mbuf.h
|
||||
* Module handling Direct Memory Access controller's multibuffer system
|
||||
*
|
||||
* The module provides a convenient tool to send data to a peripheral in a
|
||||
* buffered, low-latency, low-cpu usage, non-blocking way
|
||||
*/
|
||||
|
||||
#ifndef _DMA_MBUF_H_
|
||||
#define _DMA_MBUF_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "../drv/dma.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Struct used by the multibuffer system. This system allows bufferized writes
|
||||
* to a peripheral with controlled latency, minimal cpu usage and customisable
|
||||
* buffer size
|
||||
*/
|
||||
struct DmaMultiBuffer {
|
||||
uint8_t* raw_buffer; //the buffer to use as a multi-buffer
|
||||
|
||||
uint16_t buffer_size; //the size of the buffer
|
||||
|
||||
uint8_t byte_index; //index of the next byte to be written
|
||||
uint8_t buffer_index; //index of the buffer being written to
|
||||
enum DmaPeriph dma; //DMA peripheral used for transfers
|
||||
enum DmaChannel channel; //DMA channel used for transfers
|
||||
|
||||
bool dma_running; //whether the dam is currently running or not
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configure a DMA multibuffer for a single DMA channel. The given buffer is
|
||||
* divided into 2 to allow one part to be written to while the other is being
|
||||
* transfered by the DMA to a peripheral.
|
||||
* The peripheral's specific configuration must be handled separately.
|
||||
* Each peripheral's driver is responsible for providing the DMA configuration
|
||||
* for said peripheral, though it can be manually given too. Please note that
|
||||
* multiple peripherals may share the same DMA channel, which will cause issue
|
||||
* when used with this buffer.
|
||||
*
|
||||
* This buffer can be written to at any given time using dma_mbuf_write_byte(),
|
||||
* but its content are only written to the corresponding peripheral when
|
||||
* dma_mbuf_switch() is called.
|
||||
*/
|
||||
void dma_mbuf_configure(volatile struct DmaMultiBuffer* buffer,
|
||||
const struct DmaParam* param, enum DmaConfig priority,
|
||||
void* raw_buffer, uint16_t buffer_size);
|
||||
|
||||
/**
|
||||
* Write the given byte to the given buffer. Returns 0 if the write operation
|
||||
* was successfull, 1 otherwise. The function is non-blocking.
|
||||
*
|
||||
* Note: calling this function will not trigger a DMA transfer, see
|
||||
* dma_mbuf_switch() to do that
|
||||
*/
|
||||
uint32_t dma_mbuf_write_byte(volatile struct DmaMultiBuffer* buffer,
|
||||
uint8_t byte);
|
||||
|
||||
/**
|
||||
* Switch the buffers, triggering a DMA transfer while allowing writes to
|
||||
* continue. This function may fail if a DMA transfer is already running,
|
||||
* returning 1
|
||||
*/
|
||||
uint32_t dma_mbuf_switch(volatile struct DmaMultiBuffer* buffer);
|
||||
|
||||
|
||||
#endif //_DMA_MBUF_H_
|
||||
|
||||
50
srv/error.h
Normal file
50
srv/error.h
Normal file
@ -0,0 +1,50 @@
|
||||
/** @file error.h
|
||||
* Module providing error handling macros
|
||||
*
|
||||
* The module implements the assert macro intended to allow catching critical
|
||||
* errors during debug while having no influence in the release code as well as
|
||||
* multiple tool macros to handles other kinds of errors
|
||||
*/
|
||||
|
||||
#ifndef _ERROR_H_
|
||||
#define _ERROR_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define ERROR_ASSERT 1
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define error_to_string(arg) #arg
|
||||
|
||||
#if ERROR_ASSERT
|
||||
#define error_assert(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
debug_error("%s:l%u:%s: %s", __FILE__, __LINE__, __func__, \
|
||||
error_to_string(cond)); \
|
||||
while (true) {} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define error_assert(cond) do {} while (0)
|
||||
#endif
|
||||
|
||||
#if ERROR_ASSERT
|
||||
#define error_trigger(msg, ...) \
|
||||
do { \
|
||||
debug_error(msg __VA_OPT__(,) __VA_ARGS__); \
|
||||
while (true) {} \
|
||||
} while (0)
|
||||
#else
|
||||
#define error_trigger(msg) do {} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_ERROR_H_
|
||||
|
||||
270
srv/format.c
Normal file
270
srv/format.c
Normal file
@ -0,0 +1,270 @@
|
||||
/** @file format.c
|
||||
* Module handling various formating functions
|
||||
*
|
||||
* The module provides a lightweight printf function and the attached tools
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "format.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
struct BufferArg {
|
||||
char* restrict buffer;
|
||||
uint32_t buffer_size;
|
||||
uint32_t byte_index;
|
||||
};
|
||||
|
||||
static uint32_t buffer_write(uint8_t byte, void* arg);
|
||||
static uint32_t render_format(FormatCallback callback, void* arg,
|
||||
const char* restrict format, va_list va);
|
||||
static uint32_t render_signed(FormatCallback callback, void* arg,
|
||||
int32_t number, uint8_t base, uint8_t width);
|
||||
static uint32_t render_unsigned(FormatCallback callback, void* arg,
|
||||
uint32_t number, uint8_t base, uint8_t width, bool zero_padding);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
uint32_t format_snprintf(char* restrict buffer, uint32_t buffer_size,
|
||||
const char* restrict format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
struct BufferArg arg = { buffer, buffer_size, 0 };
|
||||
uint32_t ret = render_format(buffer_write, &arg, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t format_fctprintf(FormatCallback callback, void* arg,
|
||||
const char* restrict format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
uint32_t ret = render_format(callback, arg, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t format_vfctprintf(FormatCallback callback, void* arg,
|
||||
const char* restrict format, va_list va)
|
||||
{
|
||||
return render_format(callback, arg, format, va);
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* FormatCallback to write into a regular buffer. A pointer to BufferArg shall
|
||||
* be passed as arg.
|
||||
*
|
||||
* Returns 0 if everything went as expected, 1 otherwise
|
||||
*/
|
||||
static uint32_t buffer_write(uint8_t byte, void* arg)
|
||||
{
|
||||
error_assert(arg != nullptr);
|
||||
|
||||
struct BufferArg* buffer_arg = (struct BufferArg*)arg;
|
||||
if (buffer_arg->byte_index >= buffer_arg->buffer_size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer_arg->buffer[buffer_arg->byte_index] = byte;
|
||||
++buffer_arg->byte_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the given format to the output defined by the provided callback,
|
||||
* formatting accordingly the provided arguments
|
||||
*
|
||||
* Returns 0 if everything went as expected, 1 otherwise
|
||||
*/
|
||||
static uint32_t render_format(FormatCallback callback, void* arg,
|
||||
const char* restrict format, va_list va)
|
||||
{
|
||||
error_assert(format != nullptr);
|
||||
|
||||
uint8_t width = 0;
|
||||
bool in_format = false;
|
||||
bool zero_padding = false;
|
||||
|
||||
for (const char* c = format; *c != '\0'; ++c) {
|
||||
|
||||
if (in_format) {
|
||||
switch (*c) {
|
||||
case '%':
|
||||
if (callback('%', arg)) return 1;
|
||||
break;
|
||||
case 'c':
|
||||
if (callback((uint8_t)va_arg(va, uint32_t), arg)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
const char* str = va_arg(va, const char*);
|
||||
for (const char* c2 = str; *c2 != '\0'; ++c2) {
|
||||
if (callback(*c2, arg)) return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (render_signed(callback, arg, va_arg(va, int32_t),
|
||||
10, width)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (render_unsigned(callback, arg, va_arg(va, uint32_t),
|
||||
10, width, zero_padding)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
if (render_unsigned(callback, arg, va_arg(va, uint32_t),
|
||||
16, width, zero_padding)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
if (width == 0) {
|
||||
zero_padding = true;
|
||||
continue;
|
||||
}
|
||||
// fall through
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
width *= 10;
|
||||
width += (*c - '0');
|
||||
continue;
|
||||
default:
|
||||
error_trigger("unsupported option: %c in %s", c, format);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (*c) {
|
||||
case '%':
|
||||
in_format = true;
|
||||
zero_padding = false;
|
||||
width = 0;
|
||||
continue;
|
||||
default:
|
||||
if (callback(*c, arg)) return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in_format = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a signed integer and renders it to the output defined by the provided
|
||||
* callback
|
||||
*
|
||||
* Returns 0 if everything went as expected, 1 otherwise
|
||||
*/
|
||||
static uint32_t render_signed(FormatCallback callback, void* arg,
|
||||
int32_t number, uint8_t base, uint8_t width)
|
||||
{
|
||||
if (width > 0 && number < 0) {
|
||||
--width;
|
||||
}
|
||||
|
||||
if (width > 0) {
|
||||
uint32_t abs_number;
|
||||
if (number < 0) {
|
||||
abs_number = -number;
|
||||
} else {
|
||||
abs_number = number;
|
||||
}
|
||||
|
||||
uint32_t base_power = base;
|
||||
while (width > 0 && base_power <= abs_number) {
|
||||
base_power *= base;
|
||||
--width;
|
||||
}
|
||||
if (width > 0) {
|
||||
--width;
|
||||
}
|
||||
|
||||
while (width > 0) {
|
||||
--width;
|
||||
if (callback(' ', arg)) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (number < 0) {
|
||||
callback('-', arg);
|
||||
number = -number;
|
||||
}
|
||||
|
||||
return render_unsigned(callback, arg, (uint32_t)number, base, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an unsigned integer and renders it to the output defined by the
|
||||
* provided callback
|
||||
*
|
||||
* Returns 0 if everything went as expected, 1 otherwise
|
||||
*/
|
||||
static uint32_t render_unsigned(FormatCallback callback, void* arg,
|
||||
uint32_t number, uint8_t base, uint8_t width, bool zero_padding)
|
||||
{
|
||||
uint32_t base_power = base;
|
||||
|
||||
while (base_power <= number) {
|
||||
base_power *= base;
|
||||
if (width > 0) {
|
||||
--width;
|
||||
}
|
||||
}
|
||||
if (width > 0) {
|
||||
--width;
|
||||
}
|
||||
|
||||
while (width > 0) {
|
||||
--width;
|
||||
if (zero_padding) {
|
||||
if (callback('0', arg)) return 1;
|
||||
} else {
|
||||
if (callback(' ', arg)) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (base_power > 1) {
|
||||
base_power /= base;
|
||||
|
||||
uint8_t digit = 0;
|
||||
while (number >= base_power) {
|
||||
number -= base_power;
|
||||
++digit;
|
||||
}
|
||||
|
||||
if (digit < 10) {
|
||||
if (callback('0' + digit, arg)) return 1;
|
||||
} else {
|
||||
if (callback('A' + digit - 10, arg)) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
57
srv/format.h
Normal file
57
srv/format.h
Normal file
@ -0,0 +1,57 @@
|
||||
/** @file format.h
|
||||
* Module handling various formating functions
|
||||
*
|
||||
* The module provides a lightweight printf function and the attached tools
|
||||
*/
|
||||
|
||||
#ifndef _FORMAT_H_
|
||||
#define _FORMAT_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
typedef uint32_t (*FormatCallback)(uint8_t byte, void* arg);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Custom implementation of snprintf. Print the given format into the given
|
||||
* buffer with the attached arguments properly formated.
|
||||
*
|
||||
* This function only provided a minimal subset of the standard library's
|
||||
* snprintf : %c, %s, %i, %d, %x as well as right-justified padding for %d and
|
||||
* %x
|
||||
*
|
||||
* Returns 0 if everything went as expected, 1 otherwise
|
||||
*/
|
||||
uint32_t format_snprintf(char* restrict buffer, uint32_t buffer_size,
|
||||
const char* restrict format, ...);
|
||||
|
||||
/**
|
||||
* Custom implementation of fprintf using a callback instead of a file pointer.
|
||||
* Print the given format using the given callback with the attached arguments
|
||||
* properly formated.
|
||||
*
|
||||
* This function only provided a minimal subset of the standard library's
|
||||
* snprintf : %c, %s, %i, %d, %x as well as right-justified padding for %d and
|
||||
* %x
|
||||
*
|
||||
* Returns 0 if everything went as expected, 1 otherwise
|
||||
*/
|
||||
uint32_t format_fctprintf(FormatCallback callback, void* arg,
|
||||
const char* restrict format, ...);
|
||||
|
||||
/**
|
||||
* Variadic variation of format_fctprintf(), see the later for more information
|
||||
*/
|
||||
uint32_t format_vfctprintf(FormatCallback callback, void* arg,
|
||||
const char* restrict format, va_list va);
|
||||
|
||||
#endif //_FORMAT_H_
|
||||
|
||||
376
startup.s
Normal file
376
startup.s
Normal file
@ -0,0 +1,376 @@
|
||||
/** @file
|
||||
* Startup script to be used with the HBL
|
||||
*
|
||||
* This startup file provides a reset handler to setup the basics for c to run
|
||||
* (stack pointer, static data, ...) as well as the vector table and the
|
||||
* differents interrupt handlers that go with it. By default, all handlers use
|
||||
* the default handler wich is simply an infinite loop
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m3
|
||||
.fpu softvfp
|
||||
.thumb
|
||||
|
||||
.word _sromdata
|
||||
.word _sdata
|
||||
.word _edata
|
||||
|
||||
|
||||
//--Handler definitions---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Reset handler, first thing executed at boot
|
||||
* The handler configures the stack pointer and loads data from ROM to RAM
|
||||
*/
|
||||
.section .text.hdr_reset
|
||||
.weak hdr_reset
|
||||
.type hdr_reset, %function
|
||||
hdr_reset:
|
||||
ldr r0, = _estack
|
||||
mov sp, r0
|
||||
|
||||
//load data from ROM to RAM
|
||||
ldr r1, = _sdata
|
||||
ldr r2, = _edata
|
||||
subs r2, r2, r1
|
||||
bcc data_init_end
|
||||
ldr r3, = _sromdata
|
||||
|
||||
movs r0, #0
|
||||
|
||||
data_init_loop:
|
||||
ldr r4, [r3, r0]
|
||||
str r4, [r1, r0]
|
||||
adds r0, r0, #4
|
||||
cmp r0, r2
|
||||
bcc data_init_loop
|
||||
|
||||
data_init_end:
|
||||
//initialize RAM to zero
|
||||
ldr r1, = _sbss
|
||||
ldr r2, = _ebss
|
||||
subs r2, r2, r1
|
||||
bcc bss_init_end
|
||||
movs r3, #0
|
||||
|
||||
movs r0, #0
|
||||
|
||||
bss_init_loop:
|
||||
str r3, [r1, r0]
|
||||
adds r0, r0, #4
|
||||
cmp r0, r2
|
||||
bcc bss_init_loop
|
||||
|
||||
bss_init_end:
|
||||
b main
|
||||
b hdr_reset
|
||||
|
||||
.size hdr_reset, .-hdr_reset
|
||||
|
||||
/**
|
||||
* Default handler, called on reception of an unexpected interrupt
|
||||
* This is the handler used by default for all interrupts unless a specific
|
||||
* handler was defined elsewhere
|
||||
*/
|
||||
.section .text.hdr_default, "ax", %progbits
|
||||
.weak hdr_default
|
||||
hdr_default:
|
||||
b hdr_default
|
||||
|
||||
.size hdr_default, .-hdr_default
|
||||
|
||||
|
||||
//--Vector table----------------------------------------------------------------
|
||||
|
||||
.section .vector_table, "a", %progbits
|
||||
.type vector_table, %object
|
||||
.size vector_table, .-vector_table
|
||||
|
||||
vector_table:
|
||||
.word _estack
|
||||
.word hdr_reset
|
||||
.word hdr_nmi
|
||||
.word hdr_hard_fault
|
||||
.word hdr_mem_manage
|
||||
.word hdr_bus_fault
|
||||
.word hdr_usage_fault
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word hdr_svc
|
||||
.word hdr_debug_monitor
|
||||
.word 0
|
||||
.word hdr_pend_sys_service
|
||||
.word hdr_sys_tick
|
||||
.word hdr_wwdg
|
||||
.word hdr_pvd
|
||||
.word hdr_tamper
|
||||
.word hdr_rtc
|
||||
.word hdr_flash
|
||||
.word hdr_rcc
|
||||
.word hdr_exti0
|
||||
.word hdr_exti1
|
||||
.word hdr_exti2
|
||||
.word hdr_exti3
|
||||
.word hdr_exti4
|
||||
.word hdr_dma1_channel1
|
||||
.word hdr_dma1_channel2
|
||||
.word hdr_dma1_channel3
|
||||
.word hdr_dma1_channel4
|
||||
.word hdr_dma1_channel5
|
||||
.word hdr_dma1_channel6
|
||||
.word hdr_dma1_channel7
|
||||
.word hdr_adc1_2
|
||||
.word hdr_hp_can_tx
|
||||
.word hdr_lp_can_rx0
|
||||
.word hdr_can_rx1
|
||||
.word hdr_can_sce
|
||||
.word hdr_exti9_5
|
||||
.word hdr_tim1_brk
|
||||
.word hdr_tim1_up
|
||||
.word hdr_tim1_trg_com
|
||||
.word hdr_tim1_cc
|
||||
.word hdr_tim2
|
||||
.word hdr_tim3
|
||||
.word hdr_tim4
|
||||
.word hdr_i2c1_event
|
||||
.word hdr_i2c1_error
|
||||
.word hdr_i2c2_event
|
||||
.word hdr_i2c2_error
|
||||
.word hdr_spi1
|
||||
.word hdr_spi2
|
||||
.word hdr_usart1
|
||||
.word hdr_usart2
|
||||
.word hdr_usart3
|
||||
.word hdr_exti15_10
|
||||
.word hdr_rtc_alarm
|
||||
.word hdr_usb_wakeup
|
||||
.word hdr_tim8_brk
|
||||
.word hdr_tim8_up
|
||||
.word hdr_tim8_trg_com
|
||||
.word hdr_tim8_cc
|
||||
.word hdr_adc3
|
||||
.word hdr_fsmc
|
||||
.word hdr_sdio
|
||||
.word hdr_tim5
|
||||
.word hdr_spi3
|
||||
.word hdr_uart4
|
||||
.word hdr_uart5
|
||||
.word hdr_tim6
|
||||
.word hdr_tim7
|
||||
.word hdr_dma2_channel1
|
||||
.word hdr_dma2_channel2
|
||||
.word hdr_dma2_channel3
|
||||
.word hdr_dma2_channel4_5
|
||||
|
||||
//--Weak definitions------------------------------------------------------------
|
||||
|
||||
.weak hdr_nmi
|
||||
.thumb_set hdr_nmi, hdr_default
|
||||
|
||||
.weak hdr_hard_fault
|
||||
.thumb_set hdr_hard_fault, hdr_default
|
||||
|
||||
.weak hdr_mem_manage
|
||||
.thumb_set hdr_mem_manage, hdr_default
|
||||
|
||||
.weak hdr_bus_fault
|
||||
.thumb_set hdr_bus_fault, hdr_default
|
||||
|
||||
.weak hdr_usage_fault
|
||||
.thumb_set hdr_usage_fault, hdr_default
|
||||
|
||||
.weak hdr_svc
|
||||
.thumb_set hdr_svc, hdr_default
|
||||
|
||||
.weak hdr_debug_monitor
|
||||
.thumb_set hdr_debug_monitor, hdr_default
|
||||
|
||||
.weak hdr_pend_sys_service
|
||||
.thumb_set hdr_pend_sys_service, hdr_default
|
||||
|
||||
.weak hdr_sys_tick
|
||||
.thumb_set hdr_sys_tick, hdr_default
|
||||
|
||||
.weak hdr_wwdg
|
||||
.thumb_set hdr_wwdg, hdr_default
|
||||
|
||||
.weak hdr_pvd
|
||||
.thumb_set hdr_pvd, hdr_default
|
||||
|
||||
.weak hdr_tamper
|
||||
.thumb_set hdr_tamper, hdr_default
|
||||
|
||||
.weak hdr_rtc
|
||||
.thumb_set hdr_rtc, hdr_default
|
||||
|
||||
.weak hdr_flash
|
||||
.thumb_set hdr_flash, hdr_default
|
||||
|
||||
.weak hdr_rcc
|
||||
.thumb_set hdr_rcc, hdr_default
|
||||
|
||||
.weak hdr_exti0
|
||||
.thumb_set hdr_exti0, hdr_default
|
||||
|
||||
.weak hdr_exti1
|
||||
.thumb_set hdr_exti1, hdr_default
|
||||
|
||||
.weak hdr_exti2
|
||||
.thumb_set hdr_exti2, hdr_default
|
||||
|
||||
.weak hdr_exti3
|
||||
.thumb_set hdr_exti3, hdr_default
|
||||
|
||||
.weak hdr_exti4
|
||||
.thumb_set hdr_exti4, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel1
|
||||
.thumb_set hdr_dma_channel1, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel2
|
||||
.thumb_set hdr_dma_channel2, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel3
|
||||
.thumb_set hdr_dma_channel3, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel4
|
||||
.thumb_set hdr_dma_channel4, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel5
|
||||
.thumb_set hdr_dma_channel5, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel6
|
||||
.thumb_set hdr_dma_channel6, hdr_default
|
||||
|
||||
.weak hdr_dma1_channel7
|
||||
.thumb_set hdr_dma_channel7, hdr_default
|
||||
|
||||
.weak hdr_adc1_2
|
||||
.thumb_set hdr_adc1_2, hdr_default
|
||||
|
||||
.weak hdr_hp_can_tx
|
||||
.thumb_set hdr_hp_can_tx, hdr_default
|
||||
|
||||
.weak hdr_lp_can_rx0
|
||||
.thumb_set hdr_lp_can_rx0, hdr_default
|
||||
|
||||
.weak hdr_can_rx1
|
||||
.thumb_set hdr_can_rx1, hdr_default
|
||||
|
||||
.weak hdr_can_sce
|
||||
.thumb_set hdr_can_sce, hdr_default
|
||||
|
||||
.weak hdr_exti9_5
|
||||
.thumb_set hdr_exti9_5, hdr_default
|
||||
|
||||
.weak hdr_tim1_brk
|
||||
.thumb_set hdr_tim1_brk, hdr_default
|
||||
|
||||
.weak hdr_tim1_up
|
||||
.thumb_set hdr_tim1_up, hdr_default
|
||||
|
||||
.weak hdr_tim1_trg_com
|
||||
.thumb_set hdr_tim1_trg_com, hdr_default
|
||||
|
||||
.weak hdr_tim1_cc
|
||||
.thumb_set hdr_tim1_cc, hdr_default
|
||||
|
||||
.weak hdr_tim2
|
||||
.thumb_set hdr_tim2, hdr_default
|
||||
|
||||
.weak hdr_tim3
|
||||
.thumb_set hdr_tim3, hdr_default
|
||||
|
||||
.weak hdr_tim4
|
||||
.thumb_set hdr_tim4, hdr_default
|
||||
|
||||
.weak hdr_i2c1_event
|
||||
.thumb_set hdr_i2c1_event, hdr_default
|
||||
|
||||
.weak hdr_i2c1_error
|
||||
.thumb_set hdr_i2c1_error, hdr_default
|
||||
|
||||
.weak hdr_i2c2_event
|
||||
.thumb_set hdr_i2c2_event, hdr_default
|
||||
|
||||
.weak hdr_i2c2_error
|
||||
.thumb_set hdr_i2c2_error, hdr_default
|
||||
|
||||
.weak hdr_spi1
|
||||
.thumb_set hdr_spi1, hdr_default
|
||||
|
||||
.weak hdr_spi2
|
||||
.thumb_set hdr_spi2, hdr_default
|
||||
|
||||
.weak hdr_usart1
|
||||
.thumb_set hdr_usart1, hdr_default
|
||||
|
||||
.weak hdr_usart2
|
||||
.thumb_set hdr_usart2, hdr_default
|
||||
|
||||
.weak hdr_usart3
|
||||
.thumb_set hdr_usart3, hdr_default
|
||||
|
||||
.weak hdr_exti15_10
|
||||
.thumb_set hdr_exti15_10, hdr_default
|
||||
|
||||
.weak hdr_rtc_alarm
|
||||
.thumb_set hdr_rtc_alarm, hdr_default
|
||||
|
||||
.weak hdr_usb_wakeup
|
||||
.thumb_set hdr_usb_wakeup, hdr_default
|
||||
|
||||
.weak hdr_tim8_brk
|
||||
.thumb_set hdr_tim8_brk, hdr_default
|
||||
|
||||
.weak hdr_tim8_up
|
||||
.thumb_set hdr_tim8_up, hdr_default
|
||||
|
||||
.weak hdr_tim8_trg_com
|
||||
.thumb_set hdr_tim8_trg_com, hdr_default
|
||||
|
||||
.weak hdr_tim8_cc
|
||||
.thumb_set hdr_tim8_cc, hdr_default
|
||||
|
||||
.weak hdr_adc3
|
||||
.thumb_set hdr_adc3, hdr_default
|
||||
|
||||
.weak hdr_fsmc
|
||||
.thumb_set hdr_fsmc, hdr_default
|
||||
|
||||
.weak hdr_sdio
|
||||
.thumb_set hdr_sdio, hdr_default
|
||||
|
||||
.weak hdr_tim5
|
||||
.thumb_set hdr_tim5, hdr_default
|
||||
|
||||
.weak hdr_spi3
|
||||
.thumb_set hdr_spi3, hdr_default
|
||||
|
||||
.weak hdr_uart4
|
||||
.thumb_set hdr_uart4, hdr_default
|
||||
|
||||
.weak hdr_uart5
|
||||
.thumb_set hdr_uart5, hdr_default
|
||||
|
||||
.weak hdr_tim6
|
||||
.thumb_set hdr_tim6, hdr_default
|
||||
|
||||
.weak hdr_tim7
|
||||
.thumb_set hdr_tim7, hdr_default
|
||||
|
||||
.weak hdr_dma2_channel1
|
||||
.thumb_set hdr_dma_channel1, hdr_default
|
||||
|
||||
.weak hdr_dma2_channel2
|
||||
.thumb_set hdr_dma_channel2, hdr_default
|
||||
|
||||
.weak hdr_dma2_channel3
|
||||
.thumb_set hdr_dma_channel3, hdr_default
|
||||
|
||||
.weak hdr_dma2_channel4_5
|
||||
.thumb_set hdr_dma_channel4_5, hdr_default
|
||||
|
||||
Loading…
Reference in New Issue
Block a user