Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| daf5920814 | |||
| 70e6cd2d19 | |||
| 3303bf6435 | |||
| ec9f5f85fb | |||
| bd15878cb5 | |||
| 5ddcf4b15e | |||
| 05e3397d95 | |||
| ae9cdc3582 | |||
| a0dadf166d | |||
| a1028b29b8 | |||
| 449ec77f9f | |||
| 92085aabb0 | |||
| 6ab59f1545 | |||
| edb59d7e6b | |||
| d7da7618e3 | |||
| 3cbc836fe5 | |||
| 93f1b5a992 | |||
| 6d95bce6df | |||
| ebc7ad4235 | |||
| bc4bab4704 | |||
| a4ca0d30c3 | |||
| 89c81b8c42 | |||
| 24e412446d | |||
| 7ab6622908 | |||
| ba9bc57a49 | |||
| 947df53ecb | |||
| 80c027370b | |||
| b1d25561b4 | |||
| 507f1e6863 | |||
| 3e3d4d2bff | |||
| b37eb1dd6e | |||
| 0b483c535b | |||
| a02bcecaec | |||
| 699569ec99 | |||
| 3e97d4fe7e | |||
| 5c89df4324 | |||
| 1741d47546 | |||
| 97dad53621 | |||
| 9681755168 | |||
| 5e4d87474a | |||
| d5c70a3a04 | |||
| 93b383be49 | |||
| dd1756221d | |||
| 173e16eb2e | |||
| b7951f2211 | |||
| 7cb33f65a5 | |||
| c09d2cda67 | |||
| 34fb4dac76 | |||
| 432310a52d | |||
| 7e69bfd89c | |||
| ddd05da6eb | |||
| 7ba9063d02 | |||
| fb1c11132f | |||
|
|
cbe6409f69 | ||
|
|
64e1a0c83d | ||
| 47a06a2a39 | |||
| a20acf4031 | |||
|
|
eb0ca60aa1 | ||
| 26f2b4d545 | |||
| 12800818ce | |||
| 84deb788a0 | |||
| 254fec4f00 | |||
| 0088322ee7 | |||
| e477055e6e | |||
| 3bcb9c7df4 | |||
| 075d9e17a6 | |||
| 727aadaba9 | |||
| 3dc548332f | |||
| 0d5deffa58 | |||
|
|
c26b1cd703 | ||
| cf077d2e51 | |||
| 4eec301d17 | |||
| c6da4e11d8 | |||
| 85e7ad5ef1 | |||
| a1ae904239 | |||
| 5e961b15fc | |||
| fd33003e26 | |||
| 7a19ae9223 | |||
| ccf36ac400 | |||
| e1097048a6 | |||
| b992e2b8fb | |||
| cc54ca7ca8 | |||
| 0628c4c07c | |||
| dbfba20520 | |||
| a7099d5dfd | |||
| 086f9155f7 | |||
| 4464156981 | |||
| d84d9cef83 | |||
| e2adf48f82 | |||
| 256e3f30ab | |||
| 7a660c29d2 | |||
| dac751e466 | |||
| 9f2b337abf | |||
| b9285f2ab9 | |||
| fdc5f381f8 | |||
| a66e5733e1 | |||
| 6269cf969a | |||
| f89fe12298 | |||
| 46776ebfd3 | |||
| c571343de1 | |||
| 43cdb55c48 | |||
| 12c0b16b39 | |||
| 45452ce49e | |||
| 6ddc2266e1 | |||
| dfccfd9591 | |||
| ebe30a4a7a | |||
| 26bb798b79 | |||
| 073be3f980 | |||
| c8040cf62f | |||
| 9706979028 | |||
| c1b3f0d073 | |||
| aeba78cfcc | |||
| 3b4536bea2 | |||
| db5180d3e7 | |||
| 245b9238e9 | |||
| 3906a79315 | |||
| 9052aac1b3 | |||
| c7deded9b2 | |||
| a99b4ad0de | |||
| 8dc58b6747 | |||
| d9170ee902 | |||
| f0da0cd05c | |||
| 0034dea774 | |||
| c44dc87f43 | |||
| 2f40111dbb | |||
| 16fbf892ba | |||
| 1d8ccfdfca | |||
| 661f4a0ae5 | |||
| 691b360eb1 | |||
| 8ff2cabeab | |||
| c10ef4d2f1 | |||
| 2d83ce9f05 | |||
| 2b689c4335 | |||
| ca935a7650 | |||
| a101f07009 | |||
| 3a768d9190 | |||
| 7f7cb077dc | |||
| dd6d5fbdd1 | |||
| 50dc10b76e | |||
| c2aec8e9ed | |||
| d1e73a55c6 | |||
| 4a12fa7a3d |
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-------------------------------------------------------------
|
||||
|
||||
31
drv/afio.h
Normal file
31
drv/afio.h
Normal file
@ -0,0 +1,31 @@
|
||||
/** @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 "exti.h"
|
||||
#include "gpio.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 {
|
||||
uint32_t PIN:4;
|
||||
uint32_t PORT:3;
|
||||
uint32_t EVOE:1;
|
||||
uint32_t reserved1:24;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union MAPR {
|
||||
struct {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 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_
|
||||
|
||||
222
drv/bkp.c
Normal file
222
drv/bkp.c
Normal file
@ -0,0 +1,222 @@
|
||||
/** @file bkp.c
|
||||
* Module handling the Backup (BKP) domain functionalities.
|
||||
*
|
||||
* This module includes management of the Real Time Clock (RTC), Tamper
|
||||
* protection system and a limited space (20 bytes) for persistent data storage
|
||||
*
|
||||
* All features present in this module stay running in standby mode / when
|
||||
* no-longer powered, so long as VBAT is maintained
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "bkp.h"
|
||||
#include "bkp_regs.h"
|
||||
#include "rcc.h"
|
||||
#include "nvic.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static uint32_t compute_prescaler(uint32_t period_ms,
|
||||
enum BkpRtcClockSrc clock_src);
|
||||
static void lsi_calib_callback(enum TimIRQSource src);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct BKP* bkp_regs = (struct BKP*)BKP_BASE_ADDRESS;
|
||||
static volatile struct RCC* rcc_regs = (struct RCC*)RCC_BASE_ADDRESS;
|
||||
static volatile struct RTC* rtc_regs = (struct RTC*)RTC_BASE_ADDRESS;
|
||||
|
||||
static BkpRtcCallback rtc_callback;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
enum BkpRtcIrq irq_mask, BkpRtcCallback callback)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE);
|
||||
|
||||
//start RTC
|
||||
rcc_regs->BDCR.RTCSEL = clock_src + 1;
|
||||
rcc_regs->BDCR.RTCEN = 1;
|
||||
|
||||
uint32_t prescaler = compute_prescaler(period_ms, clock_src);
|
||||
|
||||
//wait for registers to synchronize
|
||||
rtc_regs->CRL.RSF = 0;
|
||||
while (rtc_regs->CRL.RSF != 1) {}
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
|
||||
//enable core configuration
|
||||
rtc_regs->CRL.CNF = 1;
|
||||
|
||||
//configure core registers
|
||||
rtc_regs->PRLH.PRL = prescaler >> 16;
|
||||
rtc_regs->PRLL.PRL = prescaler;
|
||||
|
||||
//apply irq config
|
||||
rtc_regs->CRH.word |= irq_mask & 0x7;
|
||||
|
||||
//disable/apply core configuration
|
||||
rtc_regs->CRL.CNF = 0;
|
||||
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
|
||||
if (callback) {
|
||||
rtc_callback = callback;
|
||||
nvic_enable(NVIC_IRQ_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
void bkp_set_rtc_alam(uint32_t offset)
|
||||
{
|
||||
uint32_t alarm = bkp_read_rtc() + offset;
|
||||
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
|
||||
//enable core configuration
|
||||
rtc_regs->CRL.CNF = 1;
|
||||
|
||||
//write alarm value
|
||||
rtc_regs->ALRH.RTC_ALR = alarm >> 16;
|
||||
rtc_regs->ALRL.RTC_ALR = alarm;
|
||||
|
||||
//disable/apply core configuration
|
||||
rtc_regs->CRL.CNF = 0;
|
||||
|
||||
//wait for last operation to finish
|
||||
while (rtc_regs->CRL.RTOFF != 1) {}
|
||||
}
|
||||
|
||||
uint32_t bkp_read_rtc(void)
|
||||
{
|
||||
//wait for core registers to be synchronized, immediate most of the time
|
||||
while (rtc_regs->CRL.RSF != 1) {}
|
||||
|
||||
uint32_t time = rtc_regs->CNTH.RTC_CNT << 16;
|
||||
time |= rtc_regs->CNTL.RTC_CNT << 0;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
uint32_t bkp_read_rtc_div(void)
|
||||
{
|
||||
//wait for core registers to be synchronized, immediate most of the time
|
||||
while (rtc_regs->CRL.RSF != 1) {}
|
||||
|
||||
uint32_t div = rtc_regs->DIVH.RTC_DIV << 16;
|
||||
div |= rtc_regs->DIVL.RTC_DIV << 0;
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
void bkp_reset(void)
|
||||
{
|
||||
rcc_regs->BDCR.BDRST = 1;
|
||||
rcc_regs->BDCR.BDRST = 0;
|
||||
}
|
||||
|
||||
void bkp_write_data(enum BkpData data_index, uint16_t data)
|
||||
{
|
||||
bkp_regs->DR[data_index].D = data;
|
||||
}
|
||||
|
||||
uint16_t bkp_read_data(enum BkpData data_index)
|
||||
{
|
||||
return bkp_regs->DR[data_index].D;
|
||||
}
|
||||
|
||||
void bkp_calibrate_lsi(enum TimPeriph timer)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_BKP, RCC_APB2_NONE);
|
||||
|
||||
//do not calibrate if already calibrated
|
||||
if (bkp_read_data(BKP_DATA_LSI_CALIB) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//configure timer to count 1s exactly
|
||||
struct RccClocks clocks;
|
||||
rcc_get_clocks(&clocks);
|
||||
|
||||
tim_set_prescaler(timer, (clocks.tim_freq / 10000)); //10000 to avoid
|
||||
//prescaler overflow
|
||||
tim_set_auto_reload(timer, 10000);
|
||||
tim_configure_master(timer, TIM_CONFIG_ONE_SHOT
|
||||
| TIM_CONFIG_DIR_UP, TIM_MASTER_CONFIG_MODE_RESET,
|
||||
lsi_calib_callback);
|
||||
|
||||
//configure rtc to tick every 2s so the div value isn't reset during the
|
||||
//timer's delay if the clock is too fast
|
||||
bkp_configure_rtc(2000, BKP_RTC_CLOCK_SRC_LSI, BKP_RTC_IRQ_NONE, nullptr);
|
||||
tim_start(timer);
|
||||
|
||||
while (bkp_read_data(BKP_DATA_LSI_CALIB) == 0) {}
|
||||
|
||||
//TODO reset timer
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Computes the prescaler value based on the clock source and the required
|
||||
* period
|
||||
*/
|
||||
static uint32_t compute_prescaler(uint32_t period_ms,
|
||||
enum BkpRtcClockSrc clock_src)
|
||||
{
|
||||
uint32_t prescaler;
|
||||
|
||||
switch (clock_src) {
|
||||
case BKP_RTC_CLOCK_SRC_LSE:
|
||||
prescaler = 32768; //32.768kHz
|
||||
break;
|
||||
case BKP_RTC_CLOCK_SRC_LSI:
|
||||
prescaler = bkp_read_data(BKP_DATA_LSI_CALIB);
|
||||
if (prescaler == 0) {
|
||||
prescaler = 40000; //40khz
|
||||
}
|
||||
break;
|
||||
case BKP_RTC_CLOCK_SRC_HSE:
|
||||
prescaler = 62500; //8Mhz / 128
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (period_ms * prescaler) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* LSI callibration callback. Measures the LSI deviation from its theorical
|
||||
* frequency using the RTC and stores the effective frequency for calibration
|
||||
* purposes
|
||||
*/
|
||||
static void lsi_calib_callback(enum TimIRQSource src)
|
||||
{
|
||||
if (src == TIM_IRQ_SOURCE_UPDATE) {
|
||||
//div is decremented from 40kHz * programmed delay (in s)
|
||||
uint32_t lsi_freq = (40000 * 2) - bkp_read_rtc_div();
|
||||
bkp_write_data(BKP_DATA_LSI_CALIB, lsi_freq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_rtc(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_RTC);
|
||||
|
||||
//copy and clear and pass along src flags
|
||||
enum BkpRtcIrq src = rtc_regs->CRL.word & 0x7;
|
||||
rtc_regs->CRL.word &= ~(0x7);
|
||||
rtc_callback(src);
|
||||
}
|
||||
|
||||
137
drv/bkp.h
Normal file
137
drv/bkp.h
Normal file
@ -0,0 +1,137 @@
|
||||
/** @file bkp.h
|
||||
* Module handling the Backup (BKP) domain functionalities.
|
||||
*
|
||||
* This module includes management of the Real Time Clock (RTC), Tamper
|
||||
* protection system and a limited space (20 bytes) for persistent data storage
|
||||
*
|
||||
* All features present in this module stay running in standby mode / when
|
||||
* no-longer powered, so long as VBAT is maintained
|
||||
*/
|
||||
|
||||
#ifndef _BKP_H_
|
||||
#define _BKP_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
#include "tim.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available clock sources for the RTC. See bkp_configure_rtc() for more
|
||||
* information
|
||||
*/
|
||||
enum BkpRtcClockSrc {
|
||||
BKP_RTC_CLOCK_SRC_LSE = 0x0,
|
||||
BKP_RTC_CLOCK_SRC_LSI = 0x1,
|
||||
BKP_RTC_CLOCK_SRC_HSE = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Available IRQ sources. This enum is passed to the RTC callback to allow
|
||||
* differentiating IRQ sources
|
||||
*/
|
||||
enum BkpRtcIrq {
|
||||
BKP_RTC_IRQ_NONE = 0,
|
||||
BKP_RTC_IRQ_SECOND = 0x1 << 0,
|
||||
BKP_RTC_IRQ_ALARM = 0x1 << 1,
|
||||
BKP_RTC_IRQ_OVERFLOW = 0x1 << 2,
|
||||
};
|
||||
|
||||
enum BkpData {
|
||||
BKP_DATA_LSI_CALIB,
|
||||
BKP_DATA_1,
|
||||
BKP_DATA_2,
|
||||
BKP_DATA_3,
|
||||
BKP_DATA_4,
|
||||
BKP_DATA_5,
|
||||
BKP_DATA_6,
|
||||
BKP_DATA_7,
|
||||
BKP_DATA_8,
|
||||
BKP_DATA_9,
|
||||
};
|
||||
|
||||
/**
|
||||
* Prototype of the IRQ callbacks that the applicative code can provide
|
||||
*/
|
||||
typedef void (*BkpRtcCallback)(enum BkpRtcIrq src);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the RTC, starting it immediately. Configuration is saved between
|
||||
* boots as long as VBAT is present
|
||||
*
|
||||
* The RTC can run on a period of up to 1s and using one of 3 clocks. Clock
|
||||
* choice is a question of compromise :
|
||||
* - LSE consumes the less energy and continues to run in standby mode, but
|
||||
* requires an extra oscillator circuit
|
||||
* - LSI consumes little but isn't very accurate and requires extra calibration
|
||||
* (see bkp_callibrate_lsi). The calibration value is automatically used if
|
||||
* present when calling this function.
|
||||
* - HSE consumes the most.
|
||||
* WARNING : once configured, the clock source can only changed by reseting the
|
||||
* whole backup domain via bkp_reset()
|
||||
* Clocks must be enabled prior to calling this function
|
||||
*
|
||||
* Mulitple IRQs can be enabled and redirected to single callback. The alarm
|
||||
* IRQ, triggered at the tick value specified by bkp_set_rtc_alam() can be
|
||||
* rerouted to an exti line for wakeup from stop and standby, in wich case it
|
||||
* doesn't need to be enabled here.
|
||||
*
|
||||
* Ensure backup domain writes are enabled (see pwr_configure_bkp_write()) while
|
||||
* calling this function
|
||||
*/
|
||||
void bkp_configure_rtc(uint32_t period_ms, enum BkpRtcClockSrc clock_src,
|
||||
enum BkpRtcIrq irq_mask, BkpRtcCallback callback);
|
||||
|
||||
/**
|
||||
* Configure the alarm to trigger after the specified time in ticks, which can
|
||||
* be viewed as an offset to the current time value. This offset is only precise
|
||||
* to the tick and thus if the tick changes right after this function is
|
||||
* called, the observed offset will be close to 1 tick short
|
||||
*/
|
||||
void bkp_set_rtc_alam(uint32_t offset);
|
||||
|
||||
/**
|
||||
* Returns the current counter value of the RTC
|
||||
*/
|
||||
uint32_t bkp_read_rtc(void);
|
||||
uint32_t bkp_read_rtc_div(void);
|
||||
|
||||
/**
|
||||
* Resets the entire backup domain, composed of everything configured through
|
||||
* this module
|
||||
*/
|
||||
void bkp_reset(void);
|
||||
|
||||
/**
|
||||
* Writes data to the specified backup domain index. The data will persist as
|
||||
* long as VBAT is present
|
||||
*/
|
||||
void bkp_write_data(enum BkpData data_index, uint16_t data);
|
||||
|
||||
/**
|
||||
* Writes data from the specified backup domain data index. The data will
|
||||
* persist as long as VBAT is present
|
||||
*/
|
||||
uint16_t bkp_read_data(enum BkpData data_index);
|
||||
|
||||
/**
|
||||
* Calibrate the LSI oscillator using the specified timer for accurate RTC
|
||||
* timings and store the calibration value at backup domain index
|
||||
* BKP_DATA_LSI_CALIB. This function has no effect if a calibration value is
|
||||
* already present
|
||||
*/
|
||||
void bkp_calibrate_lsi(enum TimPeriph timer);
|
||||
|
||||
//unimplemented functions
|
||||
void bkp_configure_tamper();
|
||||
void bkp_configure_lse(bool enable);
|
||||
|
||||
|
||||
#endif //_BKP_H_
|
||||
|
||||
197
drv/bkp_regs.h
Normal file
197
drv/bkp_regs.h
Normal file
@ -0,0 +1,197 @@
|
||||
/** @file bkp_regs.h
|
||||
* Module defining the Backup (bkp) domain registers.
|
||||
*
|
||||
* Mainly made to be used by the bkp module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _BKP_REGS_H_
|
||||
#define _BKP_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define BKP_BASE_ADDRESS 0x40006C00
|
||||
#define RCC_BASE_ADDRESS 0x40021020
|
||||
#define RTC_BASE_ADDRESS 0x40002800
|
||||
|
||||
union BKP_DR {
|
||||
struct {
|
||||
uint32_t D:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union BKP_RTCCR {
|
||||
struct {
|
||||
uint32_t CAL:7;
|
||||
uint32_t CCO:1;
|
||||
uint32_t ASOE:1;
|
||||
uint32_t ASOS:1;
|
||||
uint32_t reserved1:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union BKP_CR {
|
||||
struct {
|
||||
uint32_t TPE:1;
|
||||
uint32_t TPAL:1;
|
||||
uint32_t reserved1:30;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union BKP_CSR {
|
||||
struct {
|
||||
uint32_t CTE:1;
|
||||
uint32_t CTI:1;
|
||||
uint32_t TPIE:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t TEF:1;
|
||||
uint32_t TIF:1;
|
||||
uint32_t reserved2:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct BKP {
|
||||
uint32_t reserved1;
|
||||
union BKP_DR DR[20];
|
||||
union BKP_RTCCR RTCCR;
|
||||
union BKP_CR CR;
|
||||
union BKP_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
union RCC_BDCR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
struct RCC {
|
||||
union RCC_BDCR BDCR;
|
||||
};
|
||||
|
||||
|
||||
union RTC_CRH {
|
||||
struct {
|
||||
uint32_t SECIE:1;
|
||||
uint32_t ALRIE:1;
|
||||
uint32_t OWIE:1;
|
||||
uint32_t reserved1:29;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_CRL {
|
||||
struct {
|
||||
uint32_t SECF:1;
|
||||
uint32_t ALRF:1;
|
||||
uint32_t OWF:1;
|
||||
uint32_t RSF:1;
|
||||
uint32_t CNF:1;
|
||||
uint32_t RTOFF:1;
|
||||
uint32_t reserved1:26;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_PRLH {
|
||||
struct {
|
||||
uint32_t PRL:4;
|
||||
uint32_t reserved1:28;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_PRLL {
|
||||
struct {
|
||||
uint32_t PRL:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_DIVH {
|
||||
struct {
|
||||
uint32_t RTC_DIV:4;
|
||||
uint32_t reserved1:28;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_DIVL {
|
||||
struct {
|
||||
uint32_t RTC_DIV:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_CNTH {
|
||||
struct {
|
||||
uint32_t RTC_CNT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_CNTL {
|
||||
struct {
|
||||
uint32_t RTC_CNT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_ALRH {
|
||||
struct {
|
||||
uint32_t RTC_ALR:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union RTC_ALRL {
|
||||
struct {
|
||||
uint32_t RTC_ALR:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct RTC {
|
||||
union RTC_CRH CRH;
|
||||
union RTC_CRL CRL;
|
||||
union RTC_PRLH PRLH;
|
||||
union RTC_PRLL PRLL;
|
||||
union RTC_DIVH DIVH;
|
||||
union RTC_DIVL DIVL;
|
||||
union RTC_CNTH CNTH;
|
||||
union RTC_CNTL CNTL;
|
||||
union RTC_ALRH ALRH;
|
||||
union RTC_ALRL ALRL;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_BKP_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:
|
||||
dma1->CHANNELS[channel].CCR.EN = 0;
|
||||
if (dma1_callbacks[channel]) {
|
||||
nvic_disable(NVIC_IRQ_DMA1_CHANNEL1 + channel);
|
||||
}
|
||||
break;
|
||||
case DMA_PERIPH_2:
|
||||
dma2->CHANNELS[channel].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
|
||||
regs->CNDTR.NDT = size;
|
||||
regs->CMAR = (uint32_t)mem;
|
||||
|
||||
//only start transfer when everything is configured
|
||||
regs->CCR.EN = 1;
|
||||
}
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_dma1_channel1(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_DMA1_CHANNEL1);
|
||||
|
||||
enum DmaIRQSource src = (dma1->IFCR.word >> 1) & 0x7;
|
||||
dma1->IFCR.CGIF1 = 1;
|
||||
|
||||
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;
|
||||
dma1->IFCR.CGIF2 = 1;
|
||||
|
||||
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;
|
||||
dma1->IFCR.CGIF3 = 1;
|
||||
|
||||
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;
|
||||
dma1->IFCR.CGIF4 = 1;
|
||||
|
||||
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;
|
||||
dma1->IFCR.CGIF5 = 1;
|
||||
|
||||
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;
|
||||
dma1->IFCR.CGIF6 = 1;
|
||||
|
||||
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;
|
||||
dma1->IFCR.CGIF7 = 1;
|
||||
|
||||
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;
|
||||
dma2->IFCR.CGIF1 = 1;
|
||||
|
||||
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;
|
||||
dma2->IFCR.CGIF2 = 1;
|
||||
|
||||
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;
|
||||
dma2->IFCR.CGIF3 = 1;
|
||||
|
||||
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) {
|
||||
dma2->IFCR.CGIF4 = 1;
|
||||
dma1_callbacks[3](src, dma2_cb_params[3]);
|
||||
}
|
||||
|
||||
src = (dma2->IFCR.word >> 17) & 0x7;
|
||||
if (src != 0) {
|
||||
dma2->IFCR.CGIF5 = 1;
|
||||
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 src, 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_
|
||||
|
||||
137
drv/dma_regs.h
Normal file
137
drv/dma_regs.h
Normal file
@ -0,0 +1,137 @@
|
||||
/** @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 "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define DMA1_BASE_ADDRESS 0x40020000
|
||||
#define DMA2_BASE_ADDRESS 0x40020400
|
||||
|
||||
union DMA_ISR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union DMA_IFCR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union DMA_CCR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union DMA_CNDTR {
|
||||
struct {
|
||||
uint32_t NDT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct DMA_CHANNEL {
|
||||
union DMA_CCR CCR;
|
||||
union DMA_CNDTR CNDTR;
|
||||
uint32_t CPAR;
|
||||
uint32_t CMAR;
|
||||
uint32_t reserved1;
|
||||
};
|
||||
|
||||
struct DMA {
|
||||
union DMA_ISR ISR;
|
||||
union DMA_IFCR IFCR;
|
||||
struct DMA_CHANNEL CHANNELS[7];
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_DMA_REGS_H_
|
||||
|
||||
225
drv/exti.c
Normal file
225
drv/exti.c
Normal file
@ -0,0 +1,225 @@
|
||||
/** @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"
|
||||
|
||||
|
||||
//--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 ExtiConfig config_mask,
|
||||
ExtiCallback callback)
|
||||
{
|
||||
exti_reset(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 < 19; ++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);
|
||||
}
|
||||
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(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);
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_exti0(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI0);
|
||||
regs->PR.PR0 = 1;
|
||||
callbacks[0]();
|
||||
}
|
||||
|
||||
void hdr_exti1(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI1);
|
||||
regs->PR.PR1 = 1;
|
||||
callbacks[1]();
|
||||
}
|
||||
|
||||
void hdr_exti2(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI2);
|
||||
regs->PR.PR2 = 1;
|
||||
callbacks[2]();
|
||||
}
|
||||
|
||||
void hdr_exti3(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI3);
|
||||
regs->PR.PR3 = 1;
|
||||
callbacks[3]();
|
||||
}
|
||||
|
||||
void hdr_exti4(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_EXTI4);
|
||||
regs->PR.PR4 = 1;
|
||||
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);
|
||||
regs->PR.PR16 = 1;
|
||||
callbacks[16]();
|
||||
}
|
||||
|
||||
void hdr_rtc_alarm(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_RTC_ALARM);
|
||||
regs->PR.PR17 = 1;
|
||||
callbacks[17]();
|
||||
}
|
||||
|
||||
void hdr_usb_wakeup(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_USB_WAKEUP);
|
||||
regs->PR.PR18 = 1;
|
||||
callbacks[18]();
|
||||
}
|
||||
|
||||
88
drv/exti.h
Normal file
88
drv/exti.h
Normal file
@ -0,0 +1,88 @@
|
||||
/** @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--------------------------------------------------------------------
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Available exti lines. The numbered lines correspond to gpios while the
|
||||
* remaining are directly mapped to peripherals
|
||||
*/
|
||||
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),
|
||||
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 to call a single callback. The ExtiLine enum can be used as a
|
||||
* mask to configure multiple lines at the same time.
|
||||
*
|
||||
* Every numbered line must be linked to a gpio port using afio_map_exti(). Each
|
||||
* line is linked to the pins of the same id (ex : pin 1 for exti 1). When
|
||||
* possible, it is recommended to use the lowest id possible for better
|
||||
* performance. Each pin must be configured independently through the gpio
|
||||
* driver module
|
||||
*
|
||||
* The remaining lines are linked to specific peripherals which must be
|
||||
* configured independently through the corresponding driver module.
|
||||
*
|
||||
* 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(enum ExtiLine line_mask, enum ExtiConfig config_mask,
|
||||
ExtiCallback callback);
|
||||
|
||||
/**
|
||||
* Resets lines. The ExtiLine enum can be used as a mask to reset multiple lines
|
||||
* at the same time
|
||||
*/
|
||||
void exti_reset(enum ExtiLine line_mask);
|
||||
|
||||
/**
|
||||
* Resets all lines. The exti peripheral is returned to its reset configuration
|
||||
*/
|
||||
void exti_reset_peripheral(void);
|
||||
|
||||
|
||||
#endif //_EXTI_H_
|
||||
|
||||
190
drv/exti_regs.h
Normal file
190
drv/exti_regs.h
Normal file
@ -0,0 +1,190 @@
|
||||
/** @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 "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define EXTI_BASE_ADDRESS 0x40010400
|
||||
|
||||
union EXTI_IMR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union EXTI_EMR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union EXTI_RTSR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union EXTI_FTSR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union EXTI_SWIER {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union EXTI_PR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
struct 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_
|
||||
|
||||
52
drv/flash.c
Normal file
52
drv/flash.c
Normal file
@ -0,0 +1,52 @@
|
||||
/** @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:
|
||||
regs->ACR.HLFCYA = 1; //half cycle for power saving
|
||||
break;
|
||||
case FLASH_PRESET_MEDIUM_CLOCK_SPEED:
|
||||
regs->ACR.LATENCY = 0x1;
|
||||
break;
|
||||
case FLASH_PRESET_HIGH_CLOCK_SPEED:
|
||||
regs->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_
|
||||
|
||||
97
drv/flash_regs.h
Normal file
97
drv/flash_regs.h
Normal file
@ -0,0 +1,97 @@
|
||||
/** @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 "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define FLASH_BASE_ADDRESS 0x40022000
|
||||
|
||||
union FLASH_ACR {
|
||||
struct {
|
||||
uint32_t LATENCY:3;
|
||||
uint32_t HLFCYA:1;
|
||||
uint32_t PRFTBE:1;
|
||||
uint32_t PRFTBS:1;
|
||||
uint32_t reserved1:26;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_KEYR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_OPTKEYR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_SR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_CR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_AR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_OBR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union FLASH_WRPR {
|
||||
struct {
|
||||
uint32_t reserved1; //TODO
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct 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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 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 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 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 NVIC2 {
|
||||
uint32_t INTID;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_NVIC_REGS_H_
|
||||
|
||||
61
drv/pwr.c
Normal file
61
drv/pwr.c
Normal file
@ -0,0 +1,61 @@
|
||||
/** @file pwr.c
|
||||
* Module handling the power management's control
|
||||
*
|
||||
* The module provides functions to enter the different sleep states, control
|
||||
* and filter wakeup events (WKUP and RTC) and configure power voltage
|
||||
* detection
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "pwr.h"
|
||||
#include "pwr_regs.h"
|
||||
#include "scb.h"
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct PWR* regs = (struct PWR*)PWR_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void pwr_sleep(void)
|
||||
{
|
||||
scb_configure_deepsleep(false);
|
||||
__asm("wfe");
|
||||
}
|
||||
|
||||
void pwr_stop(enum PwrWakeupSpeed speed)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
|
||||
scb_configure_deepsleep(true);
|
||||
regs->CR.PDDS = 0;
|
||||
regs->CR.LPDS = speed;
|
||||
__asm("wfe");
|
||||
rcc_configure(RCC_PRESET_SPEED);
|
||||
}
|
||||
|
||||
void pwr_standby(void)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
|
||||
scb_configure_deepsleep(true);
|
||||
regs->CR.PDDS = 1;
|
||||
__asm("wfe");
|
||||
rcc_configure(RCC_PRESET_SPEED);
|
||||
}
|
||||
|
||||
void pwr_configure_bkp_write(bool enable)
|
||||
{
|
||||
rcc_enable(RCC_AHB_NONE, RCC_APB1_PWR, RCC_APB2_NONE);
|
||||
regs->CR.DBP = enable;
|
||||
}
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
|
||||
51
drv/pwr.h
Normal file
51
drv/pwr.h
Normal file
@ -0,0 +1,51 @@
|
||||
/** @file pwr.h
|
||||
* Module handling the power management's control
|
||||
*
|
||||
* The module provides functions to enter the different sleep states, control
|
||||
* and filter wakeup events (WKUP and RTC) and configure power voltage
|
||||
* detection
|
||||
*/
|
||||
|
||||
#ifndef _PWR_H_
|
||||
#define _PWR_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
enum PwrWakeupSpeed {
|
||||
PWR_WAKEUP_SPEED_FAST, //faster wakeup, higher consumption in stop mode
|
||||
PWR_WAKEUP_SPEED_SLOW, //slower wakeup, lower consumption in stop mode
|
||||
};
|
||||
|
||||
enum PwrPvdThreshold {
|
||||
PWR_PVD_THRESHOLD_2_2V,
|
||||
PWR_PVD_THRESHOLD_2_3V,
|
||||
PWR_PVD_THRESHOLD_2_4V,
|
||||
PWR_PVD_THRESHOLD_2_5V,
|
||||
PWR_PVD_THRESHOLD_2_6V,
|
||||
PWR_PVD_THRESHOLD_2_7V,
|
||||
PWR_PVD_THRESHOLD_2_8V,
|
||||
PWR_PVD_THRESHOLD_2_9V,
|
||||
|
||||
};
|
||||
|
||||
typedef void (*PwrPvdCallback)(void);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
void pwr_sleep(void);
|
||||
void pwr_stop(enum PwrWakeupSpeed speed);
|
||||
void pwr_standby(void);
|
||||
|
||||
bool pwr_wakeup_event(void);
|
||||
bool pwr_standby_exit(void);
|
||||
|
||||
void pwr_configure_bkp_write(bool enable);
|
||||
void pwr_configure_wakeup_pin(bool enable);
|
||||
void pwr_configure_pvd(enum PwrPvdThreshold treshold);
|
||||
|
||||
|
||||
#endif //_PWR_H_
|
||||
|
||||
56
drv/pwr_regs.h
Normal file
56
drv/pwr_regs.h
Normal file
@ -0,0 +1,56 @@
|
||||
/** @file pwr_regs.h
|
||||
* Module defining Power control (PWR) registers.
|
||||
*
|
||||
* Mainly made to be used by the pwr module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _PWR_REGS_H_
|
||||
#define _PWR_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define PWR_BASE_ADDRESS 0x40007000
|
||||
|
||||
union PWR_CR {
|
||||
struct {
|
||||
uint32_t LPDS:1;
|
||||
uint32_t PDDS:1;
|
||||
uint32_t CWUF:1;
|
||||
uint32_t CSBF:1;
|
||||
uint32_t PVDE:1;
|
||||
uint32_t PLS:3;
|
||||
uint32_t DBP:1;
|
||||
uint32_t reserved1:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union PWR_CSR {
|
||||
struct {
|
||||
uint32_t WUF:1;
|
||||
uint32_t SBF:1;
|
||||
uint32_t PVDO:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t EWUP:1;
|
||||
uint32_t reserved2:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct PWR {
|
||||
union PWR_CR CR;
|
||||
union PWR_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_PWR_REGS_H_
|
||||
|
||||
196
drv/rcc.c
Normal file
196
drv/rcc.c
Normal file
@ -0,0 +1,196 @@
|
||||
/** @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_configure_lsi(bool enable)
|
||||
{
|
||||
regs->CSR.LSION = enable;
|
||||
|
||||
//ensure LSI is enabled
|
||||
if (enable) {
|
||||
while (regs->CSR.LSIRDY != 0x1) {}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
clocks->ahb_freq = 0;
|
||||
switch (current_preset)
|
||||
{
|
||||
case RCC_PRESET_DEFAULT:
|
||||
clocks->ahb_freq = 8000000;
|
||||
clocks->apb1_freq = 8000000;
|
||||
clocks->apb2_freq = 8000000;
|
||||
clocks->tim_freq = 8000000;
|
||||
break;
|
||||
case RCC_PRESET_SPEED:
|
||||
clocks->ahb_freq = 72000000;
|
||||
clocks->apb1_freq = 36000000;
|
||||
clocks->apb2_freq = 72000000;
|
||||
clocks->tim_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
|
||||
regs->CR.HSION = 1;
|
||||
while (regs->CR.HSIRDY != 0x1);
|
||||
|
||||
//set HSI as main clock source and disable prescalers
|
||||
regs->CFGR.word &= ~0x077fff3;
|
||||
|
||||
//disable all options
|
||||
regs->CR.HSITRIM = 0;
|
||||
regs->CR.HSITRIM = 0x10;
|
||||
regs->CR.HSEON = 0;
|
||||
regs->CR.HSEBYP = 0;
|
||||
regs->CR.CCSON = 0;
|
||||
regs->CR.PLLON = 0;
|
||||
|
||||
//disable all interrupts
|
||||
regs->CIR.LSIRDYIE = 0;
|
||||
regs->CIR.LSERDYIE = 0;
|
||||
regs->CIR.HSIRDYIE = 0;
|
||||
regs->CIR.HSERDYIE = 0;
|
||||
regs->CIR.PLLRDYIE = 0;
|
||||
|
||||
//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
|
||||
regs->CR.HSEON = 1;
|
||||
for (uint32_t i=0; i<1000; ++i) {
|
||||
__asm__("nop");
|
||||
}
|
||||
if (regs->CR.HSERDY == 0x1) {
|
||||
regs->CFGR.PLLSCR = 1;
|
||||
} else {
|
||||
regs->CR.HSEON = 0;
|
||||
}
|
||||
|
||||
//configure PLL, fallback to HSI if PLL fails
|
||||
regs->CFGR.PLLMUL = 0x7; //PLL x9
|
||||
regs->CR.PLLON = 1;
|
||||
for (uint32_t i=0; i<1000; ++i) {
|
||||
__asm__("nop");
|
||||
}
|
||||
if (regs->CR.PLLRDY != 0x1) {
|
||||
regs->CR.PLLON = 0;
|
||||
return; //clock low enough, no need for prescalers
|
||||
}
|
||||
|
||||
//configure prescalers
|
||||
regs->CFGR.PPRE1 = 0x4; // /2
|
||||
regs->CFGR.ADCPRE = 0x2; // /6
|
||||
|
||||
//reconfigure flash
|
||||
flash_configure(FLASH_PRESET_HIGH_CLOCK_SPEED);
|
||||
|
||||
//switch to PLL output
|
||||
regs->CFGR.SW = 0x2;
|
||||
}
|
||||
|
||||
156
drv/rcc.h
Normal file
156
drv/rcc.h
Normal file
@ -0,0 +1,156 @@
|
||||
/** @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),
|
||||
};
|
||||
|
||||
enum RccRtcClockSrc {
|
||||
RCC_RTC_CLOCK_SRC_NONE = 0x0,
|
||||
RCC_RTC_CLOCK_SRC_LSE = 0x1,
|
||||
RCC_RTC_CLOCK_SRC_LSI = 0x2,
|
||||
RCC_RTC_CLOCK_SRC_HSE = 0x3,
|
||||
};
|
||||
|
||||
struct RccClocks {
|
||||
uint32_t ahb_freq;
|
||||
uint32_t apb1_freq;
|
||||
uint32_t apb2_freq;
|
||||
uint32_t tim_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);
|
||||
|
||||
/**
|
||||
* Configures the Low Speed Internal (LSI) oscillator for low power
|
||||
* applications.
|
||||
*/
|
||||
void rcc_configure_lsi(bool enable);
|
||||
|
||||
/**
|
||||
* 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_
|
||||
|
||||
262
drv/rcc_regs.h
Normal file
262
drv/rcc_regs.h
Normal file
@ -0,0 +1,262 @@
|
||||
/** @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 "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define RCC_BASE_ADDRESS 0x40021000
|
||||
|
||||
union RCC_CR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_CFGR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_CIR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_APB2RSTR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_APB1RSTR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_AHBENR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_APB2ENR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_APB1ENR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union RCC_CSR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
struct 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;
|
||||
uint32_t reserved1;
|
||||
union RCC_CSR CSR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_RCC_REGS_H_
|
||||
|
||||
64
drv/scb.c
Normal file
64
drv/scb.c
Normal file
@ -0,0 +1,64 @@
|
||||
/** @file scb.c
|
||||
* Module handling the System Control Block
|
||||
*
|
||||
* The module provides functions to configure miscelaneous options of the cortex
|
||||
* m3, including sleep behavior, event handler priorities, resets and fault
|
||||
* handlers
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "scb.h"
|
||||
#include "scb_regs.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static volatile struct SCB* regs = (struct SCB*)SCB_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
uint16_t scb_pending_exception(void)
|
||||
{
|
||||
return regs->ICSR.VECTPENDING;
|
||||
}
|
||||
|
||||
uint16_t scb_active_exception(void)
|
||||
{
|
||||
return regs->ICSR.VECTACTIVE;
|
||||
}
|
||||
|
||||
void scb_configure_vector_table(uint32_t offset)
|
||||
{
|
||||
//TODO check that last LSB is 0 (alignement restrictions)
|
||||
regs->VTOR.TABLEOFF = offset & 0x1FFFFF;
|
||||
}
|
||||
|
||||
void scb_reset_system(void)
|
||||
{
|
||||
regs->AIRCR.SYSRESETREQ = 1;
|
||||
}
|
||||
|
||||
void scb_configure_deepsleep(bool enable)
|
||||
{
|
||||
regs->SCR.SLEEPDEEP = enable;
|
||||
}
|
||||
|
||||
void scb_configure_div0_fault(bool enable)
|
||||
{
|
||||
regs->CCR.DIV_0_TRP = enable;
|
||||
}
|
||||
|
||||
void scb_configure_unalign_fault(bool enable)
|
||||
{
|
||||
regs->CCR.UNALIGN_TRP = enable;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
32
drv/scb.h
Normal file
32
drv/scb.h
Normal file
@ -0,0 +1,32 @@
|
||||
/** @file scb.h
|
||||
* Module handling the System Control Block
|
||||
*
|
||||
* The module provides functions to configure miscelaneous options of the cortex
|
||||
* m3, including sleep behavior, event handler priorities, resets and fault
|
||||
* handlers
|
||||
*/
|
||||
|
||||
#ifndef _SCB_H_
|
||||
#define _SCB_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
uint16_t scb_pending_exception(void);
|
||||
uint16_t scb_active_exception(void);
|
||||
|
||||
void scb_configure_vector_table(uint32_t offset);
|
||||
void scb_reset_system(void);
|
||||
void scb_configure_deepsleep(bool enable);
|
||||
void scb_configure_div0_fault(bool enable);
|
||||
void scb_configure_unalign_fault(bool enable);
|
||||
|
||||
|
||||
#endif //_SCB_H_
|
||||
|
||||
192
drv/scb_regs.h
Normal file
192
drv/scb_regs.h
Normal file
@ -0,0 +1,192 @@
|
||||
/** @file scb_regs.h
|
||||
* Module defining System Control Block (SCB) registers.
|
||||
*
|
||||
* Mainly made to be used by the scb module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _SCB_REGS_H_
|
||||
#define _SCB_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define SCB_BASE_ADDRESS 0xE000ED00
|
||||
|
||||
union SCB_CPUID {
|
||||
struct {
|
||||
uint32_t revision:4;
|
||||
uint32_t part_no:12;
|
||||
uint32_t constant:4;
|
||||
uint32_t variant:4;
|
||||
uint32_t implementer:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_ICSR {
|
||||
struct {
|
||||
uint32_t VECTACTIVE:9;
|
||||
uint32_t reserved1:2;
|
||||
uint32_t RETOBASE:1;
|
||||
uint32_t VECTPENDING:10;
|
||||
uint32_t ISRPENDING:1;
|
||||
uint32_t reserved2:2;
|
||||
uint32_t PENDSTCLR:1;
|
||||
uint32_t PENDSTSET:1;
|
||||
uint32_t PENDSVCRL:1;
|
||||
uint32_t PENDSVSET:1;
|
||||
uint32_t reserved3:2;
|
||||
uint32_t NMIPENDSET:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_VTOR {
|
||||
struct {
|
||||
uint32_t reserved1:9;
|
||||
uint32_t TABLEOFF:21;
|
||||
uint32_t reserved2:2;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_AIRCR {
|
||||
struct {
|
||||
uint32_t VECTRESET:1;
|
||||
uint32_t VECTCRLACTIVE:1;
|
||||
uint32_t SYSRESETREQ:1;
|
||||
uint32_t reserved1:5;
|
||||
uint32_t PRIGROUP:3;
|
||||
uint32_t reserved2:4;
|
||||
uint32_t ENDIANESS:1;
|
||||
uint32_t VECTKEY:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SCR {
|
||||
struct {
|
||||
uint32_t reserved1:1;
|
||||
uint32_t SLEEPONEXIT:1;
|
||||
uint32_t SLEEPDEEP:1;
|
||||
uint32_t reserved2:1;
|
||||
uint32_t SEVONPEND:1;
|
||||
uint32_t reserved3:27;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_CCR {
|
||||
struct {
|
||||
uint32_t NONBASETHRDEN:1;
|
||||
uint32_t USERSETMPEND:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t UNALIGN_TRP:1;
|
||||
uint32_t DIV_0_TRP:1;
|
||||
uint32_t reserved2:3;
|
||||
uint32_t BFHFNIGN:1;
|
||||
uint32_t STKALIGN:1;
|
||||
uint32_t reserved3:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHPR1 {
|
||||
struct {
|
||||
uint32_t PRI4:8;
|
||||
uint32_t PRI5:8;
|
||||
uint32_t PRI6:8;
|
||||
uint32_t reserved1:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHPR2 {
|
||||
struct {
|
||||
uint32_t reserved1:24;
|
||||
uint32_t PRI11:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHPR3 {
|
||||
struct {
|
||||
uint32_t reserved1:16;
|
||||
uint32_t PRI14:8;
|
||||
uint32_t PRI15:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_SHCRS {
|
||||
struct {
|
||||
uint32_t MEMFAULTACT:1;
|
||||
uint32_t BUSFAULTACT:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t USGFAULTACT:1;
|
||||
uint32_t reserved2:3;
|
||||
uint32_t SVCALLACT:1;
|
||||
uint32_t MONITORACT:1;
|
||||
uint32_t reserved3:1;
|
||||
uint32_t PENDSVACT:1;
|
||||
uint32_t SYSTICKACT:1;
|
||||
uint32_t USGFAULTPENDED:1;
|
||||
uint32_t MEMFAULTPENDED:1;
|
||||
uint32_t BUSFAULTPENDED:1;
|
||||
uint32_t SVCALLPENDED:1;
|
||||
uint32_t MEMFAULTENA:1;
|
||||
uint32_t BUSFAULTENA:1;
|
||||
uint32_t USGFAULTENA:1;
|
||||
uint32_t reserved4:13;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_CFSR {
|
||||
struct {
|
||||
uint32_t MMFSR:8;
|
||||
uint32_t BFSR:8;
|
||||
uint32_t UFSR:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union SCB_HFSR {
|
||||
struct {
|
||||
uint32_t reserved1:1;
|
||||
uint32_t VECTTBL:1;
|
||||
uint32_t reserved2:28;
|
||||
uint32_t FORCED:1;
|
||||
uint32_t DEBUG_VT:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct SCB {
|
||||
union SCB_CPUID CPUID;
|
||||
union SCB_ICSR ICSR;
|
||||
union SCB_VTOR VTOR;
|
||||
union SCB_AIRCR AIRCR;
|
||||
union SCB_SCR SCR;
|
||||
union SCB_CCR CCR;
|
||||
union SCB_SHPR1 SHPR1;
|
||||
union SCB_SHPR2 SHPR2;
|
||||
union SCB_SHPR3 SHPR3;
|
||||
union SCB_SHCRS SHCRS;
|
||||
union SCB_CFSR CFSR;
|
||||
union SCB_HFSR HFSR;
|
||||
uint32_t MMAR;
|
||||
uint32_t BFAR;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_PWR_REGS_H_
|
||||
|
||||
90
drv/stk.c
Normal file
90
drv/stk.c
Normal file
@ -0,0 +1,90 @@
|
||||
/** @file stk.c
|
||||
* Module handling the system timer (systick or STK for short)
|
||||
*
|
||||
* The module provides functions to configure and use the system timer embedded
|
||||
* in the cortex m core
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stk.h"
|
||||
#include "stk_regs.h"
|
||||
|
||||
#include "rcc.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static volatile struct STK* regs = (struct STK*)STK_BASE_ADDRESS;
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static StkCallback callback;
|
||||
static uint32_t prescaler;
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
uint32_t stk_configure(uint32_t period_us, StkCallback cb)
|
||||
{
|
||||
stk_reset();
|
||||
|
||||
struct RccClocks clocks;
|
||||
rcc_get_clocks(&clocks);
|
||||
|
||||
uint32_t prescaler = (clocks.ahb_freq / 1000000 / 8);
|
||||
uint32_t reload = period_us * prescaler;
|
||||
if (reload < 1) {
|
||||
//period is too small, try using the non-prescaled clock
|
||||
prescaler *= 8;
|
||||
reload = period_us * prescaler;
|
||||
if (reload < 1) {
|
||||
//period is still too small
|
||||
return 1;
|
||||
}
|
||||
regs->CTRL.CLKSOURCE = 1;
|
||||
}
|
||||
regs->LOAD.RELOAD = reload;
|
||||
regs->CTRL.TICKINT = 1;
|
||||
|
||||
callback = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stk_reset(void)
|
||||
{
|
||||
regs->CTRL.ENABLE = 0;
|
||||
regs->CTRL.TICKINT = 0;
|
||||
regs->CTRL.CLKSOURCE = 0;
|
||||
regs->CTRL.COUNTFLAG = 0;
|
||||
|
||||
regs->LOAD.RELOAD = 0;
|
||||
regs->VAL.CURRENT = 0;
|
||||
}
|
||||
|
||||
void stk_start(void)
|
||||
{
|
||||
regs->CTRL.ENABLE = 1;
|
||||
}
|
||||
|
||||
void stk_stop(void)
|
||||
{
|
||||
regs->CTRL.ENABLE = 0;
|
||||
}
|
||||
|
||||
uint32_t stk_read_us(void)
|
||||
{
|
||||
return (regs->VAL.word & 0x00FFFFFF) / prescaler;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
void hdr_sys_tick(void)
|
||||
{
|
||||
//clearing the pending bit in SCB_ICSR isn't needed, though I don't know why
|
||||
callback();
|
||||
}
|
||||
|
||||
55
drv/stk.h
Normal file
55
drv/stk.h
Normal file
@ -0,0 +1,55 @@
|
||||
/** @file stk.h
|
||||
* Module handling the system timer (systick or STK for short)
|
||||
*
|
||||
* The module provides functions to configure and use the system timer embedded
|
||||
* in the cortex m core
|
||||
*/
|
||||
|
||||
#ifndef _STK_H_
|
||||
#define _STK_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
typedef void (*StkCallback)(void);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the system timer to run at the specified period in µs and call the
|
||||
* given callback when said period is reached. Due to the limited configuration
|
||||
* options, 1.8s is the maximum period when running in speed preset (see rcc
|
||||
* module). The maximum period can be substantially increased by reducing the
|
||||
* core clock
|
||||
*/
|
||||
uint32_t stk_configure(uint32_t period_us, StkCallback cb);
|
||||
|
||||
/**
|
||||
* Resets the system timer configuration, restoring the default configuration
|
||||
* and stopping it
|
||||
*/
|
||||
void stk_reset(void);
|
||||
|
||||
/**
|
||||
* Starts the system timer. The timer will run until stopped
|
||||
*/
|
||||
void stk_start(void);
|
||||
|
||||
/**
|
||||
* Stops the system timer
|
||||
*/
|
||||
void stk_stop(void);
|
||||
|
||||
/**
|
||||
* Read the current value of the timer's counter in µs
|
||||
*/
|
||||
uint32_t stk_read_us(void);
|
||||
|
||||
|
||||
#endif //_STK_H_
|
||||
|
||||
70
drv/stk_regs.h
Normal file
70
drv/stk_regs.h
Normal file
@ -0,0 +1,70 @@
|
||||
/** @file stk_regs.h
|
||||
* Module defining systick (STK) registers.
|
||||
*
|
||||
* Mainly made to be used by the stk module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _STK_REGS_H_
|
||||
#define _STK_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define STK_BASE_ADDRESS 0xE000E010
|
||||
|
||||
union STK_CTRL {
|
||||
struct {
|
||||
uint32_t ENABLE:1;
|
||||
uint32_t TICKINT:1;
|
||||
uint32_t CLKSOURCE:1;
|
||||
uint32_t reserved1:13;
|
||||
uint32_t COUNTFLAG:1;
|
||||
uint32_t reserved2:15;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union STK_LOAD {
|
||||
struct {
|
||||
uint32_t RELOAD:24;
|
||||
uint32_t reserved1:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union STK_VAL {
|
||||
struct {
|
||||
uint32_t CURRENT:24;
|
||||
uint32_t reserved1:8;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union STK_CALIB {
|
||||
struct {
|
||||
uint32_t TENMS:24;
|
||||
uint32_t reserved1:6;
|
||||
uint32_t SKEW:1;
|
||||
uint32_t NOREF:1;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct STK {
|
||||
union STK_CTRL CTRL;
|
||||
union STK_LOAD LOAD;
|
||||
union STK_VAL VAL;
|
||||
union STK_CALIB CALIB;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_STK_REGS_H_
|
||||
|
||||
183
drv/tim.c
Normal file
183
drv/tim.c
Normal file
@ -0,0 +1,183 @@
|
||||
/** @file tim.c
|
||||
* Module handling general purpose and advances TIMers
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "tim.h"
|
||||
#include "tim_regs.h"
|
||||
#include "nvic.h"
|
||||
|
||||
#include "../srv/error.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
static volatile struct TIM* regs[] = {
|
||||
(struct TIM*)TIM1_BASE_ADDRESS,
|
||||
(struct TIM*)TIM2_BASE_ADDRESS,
|
||||
(struct TIM*)TIM3_BASE_ADDRESS,
|
||||
(struct TIM*)TIM4_BASE_ADDRESS,
|
||||
};
|
||||
|
||||
static enum TimIRQSource computeIRQSource(enum TimPeriph periph);
|
||||
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
static TimCallback callbacks[4];
|
||||
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
|
||||
enum TimMasterConfig master_config_mask, TimCallback callback)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
|
||||
//apply config mask directly while masking reserved areas. Masking is
|
||||
//important here since advanced timer may have additionnal config bits
|
||||
regs[periph]->cr1.word |= config_mask & 0x3FF;
|
||||
|
||||
regs[periph]->cr2.word |= (config_mask >> 16) & 0x88;
|
||||
regs[periph]->cr2.word |= master_config_mask & 0x70;
|
||||
|
||||
//if callback specified, configure IRQ
|
||||
if (callback != nullptr) {
|
||||
callbacks[periph] = callback;
|
||||
|
||||
regs[periph]->dier.TIE = 1;
|
||||
regs[periph]->dier.UIE = 0;
|
||||
|
||||
enum NvicIrq irq = 0;
|
||||
switch (periph) {
|
||||
case TIM_PERIPH_1:
|
||||
irq = NVIC_IRQ_TIM1_UP;
|
||||
break;
|
||||
case TIM_PERIPH_2:
|
||||
irq = NVIC_IRQ_TIM2;
|
||||
break;
|
||||
case TIM_PERIPH_3:
|
||||
irq = NVIC_IRQ_TIM3;
|
||||
break;
|
||||
case TIM_PERIPH_4:
|
||||
irq = NVIC_IRQ_TIM4;
|
||||
break;
|
||||
|
||||
}
|
||||
nvic_enable(irq);
|
||||
}
|
||||
|
||||
//trigger update to force application of the config
|
||||
regs[periph]->egr.UG = 1;
|
||||
while (regs[periph]->sr.UIF == 0) {}
|
||||
regs[periph]->sr.UIF = 0;
|
||||
|
||||
if (callback != nullptr) {
|
||||
regs[periph]->dier.UIE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void tim_start(enum TimPeriph periph)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
regs[periph]->cr1.CEN = 1;
|
||||
}
|
||||
|
||||
void tim_stop(enum TimPeriph periph)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
regs[periph]->cr1.CEN = 0;
|
||||
}
|
||||
|
||||
void tim_update(enum TimPeriph periph)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
regs[periph]->egr.UG = 1;
|
||||
}
|
||||
|
||||
void tim_set_auto_reload(enum TimPeriph periph, uint16_t auto_reload)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
regs[periph]->arr.ARR = auto_reload;
|
||||
}
|
||||
|
||||
void tim_set_prescaler(enum TimPeriph periph, uint16_t prescaler)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
regs[periph]->psc.PSC = prescaler;
|
||||
}
|
||||
|
||||
void tim_set_counter(enum TimPeriph periph, uint16_t counter)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
regs[periph]->cnt.CNT = counter;
|
||||
}
|
||||
|
||||
uint16_t tim_get_auto_reload(enum TimPeriph periph)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
return regs[periph]->arr.ARR;
|
||||
}
|
||||
|
||||
uint16_t tim_get_prescaler(enum TimPeriph periph)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
return regs[periph]->psc.PSC;
|
||||
}
|
||||
|
||||
uint16_t tim_get_counter(enum TimPeriph periph)
|
||||
{
|
||||
error_assert(periph <= TIM_PERIPH_4);
|
||||
return regs[periph]->cnt.CNT;
|
||||
}
|
||||
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
static enum TimIRQSource computeIRQSource(enum TimPeriph periph)
|
||||
{
|
||||
enum TimIRQSource src =
|
||||
(TIM_IRQ_SOURCE_TRIGGER & regs[periph]->sr.TIF)
|
||||
| (TIM_IRQ_SOURCE_UPDATE & regs[periph]->sr.UIF);
|
||||
regs[periph]->sr.TIF = 0;
|
||||
regs[periph]->sr.UIF = 0;
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
//--ISRs------------------------------------------------------------------------
|
||||
|
||||
void hdr_tim1_up(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_TIM1_UP);
|
||||
|
||||
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_1);
|
||||
callbacks[TIM_PERIPH_1](src);
|
||||
}
|
||||
|
||||
void hdr_tim2(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_TIM2);
|
||||
|
||||
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_2);
|
||||
callbacks[TIM_PERIPH_2](src);
|
||||
}
|
||||
|
||||
void hdr_tim3(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_TIM3);
|
||||
|
||||
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_3);
|
||||
callbacks[TIM_PERIPH_3](src);
|
||||
}
|
||||
|
||||
void hdr_tim4(void)
|
||||
{
|
||||
nvic_clear_pending(NVIC_IRQ_TIM4);
|
||||
|
||||
enum TimIRQSource src = computeIRQSource(TIM_PERIPH_4);
|
||||
callbacks[TIM_PERIPH_4](src);
|
||||
}
|
||||
|
||||
163
drv/tim.h
Normal file
163
drv/tim.h
Normal file
@ -0,0 +1,163 @@
|
||||
/** @file tim.h
|
||||
* Module handling general purpose and advances TIMers
|
||||
*/
|
||||
|
||||
#ifndef _TIM_H_
|
||||
#define _TIM_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
enum TimPeriph {
|
||||
TIM_PERIPH_1,
|
||||
TIM_PERIPH_2,
|
||||
TIM_PERIPH_3,
|
||||
TIM_PERIPH_4,
|
||||
};
|
||||
|
||||
enum TimChannel {
|
||||
TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2,
|
||||
TIM_CHANNEL_3,
|
||||
TIM_CHANNEL_4,
|
||||
};
|
||||
|
||||
enum TimConfig {
|
||||
TIM_CONFIG_DISABLE_UPDATES = (0x1 << 1),
|
||||
TIM_CONFIG_LIMIT_UPDATE_SRC = (0x1 << 2),
|
||||
TIM_CONFIG_CONTINUOUS = (0x0 << 3),
|
||||
TIM_CONFIG_ONE_SHOT = (0x1 << 3),
|
||||
TIM_CONFIG_DIR_UP = (0x0 << 4),
|
||||
TIM_CONFIG_DIR_DOWN = (0x1 << 4),
|
||||
TIM_CONFIG_CENTER_ALIGNED_1 = (0x1 << 5),
|
||||
TIM_CONFIG_CENTER_ALIGNED_2 = (0x2 << 5),
|
||||
TIM_CONFIG_CENTER_ALIGNED_3 = (0x3 << 5),
|
||||
TIM_CONFIG_BUFFERED_ARR = (0x1 << 7),
|
||||
TIM_CONFIG_FILTER_CLOCK_DIV_1 = (0x0 << 8),
|
||||
TIM_CONFIG_FILTER_CLOCK_DIV_2 = (0x1 << 8),
|
||||
TIM_CONFIG_FILTER_CLOCK_DIV_4 = (0x2 << 8),
|
||||
TIM_CONFIG_DMA_ON_CC_EVENT = (0x0 << 19),
|
||||
TIM_CONFIG_DMA_ON_UPDATE = (0x1 << 19),
|
||||
TIM_CONFIG_XOR_TI1 = (0x1 << 23),
|
||||
};
|
||||
|
||||
enum TimMasterConfig {
|
||||
TIM_MASTER_CONFIG_MODE_RESET = (0x0 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_ENABLE = (0x1 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_UPDATE = (0x2 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_COMP_PULSE = (0x3 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_COMP_1 = (0x4 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_COMP_2 = (0x5 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_COMP_3 = (0x6 << 4),
|
||||
TIM_MASTER_CONFIG_MODE_COMP_4 = (0x7 << 4),
|
||||
|
||||
};
|
||||
|
||||
enum TimSlaveConfig {
|
||||
TIM_SLAVE_CONFIG_MODE_ENCODER_1 = (0x1 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_ENCODER_2 = (0x2 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_ENCODER_3 = (0x3 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_RESET = (0x4 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_GATED = (0x5 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_TRIGGER = (0x6 << 0),
|
||||
TIM_SLAVE_CONFIG_MODE_EXT_CLK = (0x7 << 0),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_1 = (0x0 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_2 = (0x1 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_3 = (0x2 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_INTERNAL_4 = (0x3 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_EDGE_DETECT = (0x4 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_FILTERED_1 = (0x5 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_FILTERED_2 = (0x6 << 4),
|
||||
TIM_SLAVE_CONFIG_TRIG_EXT = (0x7 << 4),
|
||||
};
|
||||
|
||||
enum TimExtConfig {
|
||||
TIM_EXT_CONFIG_FILTER_1 = (0x1 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_2 = (0x2 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_3 = (0x3 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_4 = (0x4 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_5 = (0x5 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_6 = (0x6 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_7 = (0x7 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_8 = (0x8 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_9 = (0x9 << 8),
|
||||
TIM_EXT_CONFIG_FILTER_10 = (0xA << 8),
|
||||
TIM_EXT_CONFIG_FILTER_11 = (0xB << 8),
|
||||
TIM_EXT_CONFIG_FILTER_12 = (0xC << 8),
|
||||
TIM_EXT_CONFIG_FILTER_13 = (0xD << 8),
|
||||
TIM_EXT_CONFIG_FILTER_14 = (0xE << 8),
|
||||
TIM_EXT_CONFIG_FILTER_15 = (0xF << 8),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_1 = (0x0 << 12),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_2 = (0x1 << 12),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_4 = (0x2 << 12),
|
||||
TIM_EXT_CONFIG_PRESCALER_DIV_8 = (0x3 << 12),
|
||||
TIM_EXT_CONFIG_USE_AS_CLK = (0x3 << 14),
|
||||
TIM_EXT_CONFIG_INVERT = (0x3 << 15),
|
||||
};
|
||||
|
||||
enum TimOutputConfig {
|
||||
TIM_OUTPUT_CONFIG_FAST_MODE = (0x1 << 2),
|
||||
TIM_OUTPUT_CONFIG_PRELOAD_EN = (0x1 << 3),
|
||||
TIM_OUTPUT_CONFIG_MODE_FROZEN = (0x0 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_ACTIVE = (0x1 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_INACTIVE = (0x2 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_TOGGLE = (0x3 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_FORCE_ACTIVE = (0x4 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_FORCE_INACTIVE = (0x5 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_PWM_1 = (0x6 << 4),
|
||||
TIM_OUTPUT_CONFIG_MODE_PWM_2 = (0x7 << 4),
|
||||
TIM_OUTPUT_CONFIG_CLEAR_ON_EXT_TRIG = (0x1 << 7),
|
||||
};
|
||||
|
||||
enum TimIntputConfig {
|
||||
TIM_INPUT_CONFIG_ALTERNATE_TRIGGER = (0x2 << 0),
|
||||
TIM_INPUT_CONFIG_INTERNAL_TRIGGER = (0x3 << 0),
|
||||
TIM_INPUT_CONFIG_PRESCALER_1 = (0x0 << 2),
|
||||
TIM_INPUT_CONFIG_PRESCALER_2 = (0x1 << 2),
|
||||
TIM_INPUT_CONFIG_PRESCALER_4 = (0x2 << 2),
|
||||
TIM_INPUT_CONFIG_PRESCALER_8 = (0x3 << 2),
|
||||
};
|
||||
|
||||
enum TimIRQSource {
|
||||
TIM_IRQ_SOURCE_TRIGGER,
|
||||
TIM_IRQ_SOURCE_UPDATE,
|
||||
};
|
||||
|
||||
typedef void (*TimCallback)(enum TimIRQSource src);
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
|
||||
void tim_configure_master(enum TimPeriph periph, enum TimConfig config_mask,
|
||||
enum TimMasterConfig master_config_mask, TimCallback callback);
|
||||
void tim_configure_slave(enum TimPeriph periph, enum TimConfig config_mask,
|
||||
enum TimSlaveConfig slave_config_mask, TimCallback callback);
|
||||
|
||||
void tim_start(enum TimPeriph periph);
|
||||
void tim_stop(enum TimPeriph periph);
|
||||
void tim_update(enum TimPeriph periph);
|
||||
|
||||
void tim_set_auto_reload(enum TimPeriph periph, uint16_t auto_reload);
|
||||
void tim_set_prescaler(enum TimPeriph periph, uint16_t prescaler);
|
||||
void tim_set_counter(enum TimPeriph periph, uint16_t counter);
|
||||
|
||||
uint16_t tim_get_auto_reload(enum TimPeriph periph);
|
||||
uint16_t tim_get_prescaler(enum TimPeriph periph);
|
||||
uint16_t tim_get_counter(enum TimPeriph periph);
|
||||
|
||||
void tim_configure_output_channel(enum TimPeriph periph,
|
||||
enum TimChannel channel_mask, enum TimOutputConfig config_mask,
|
||||
uint16_t value);
|
||||
void tim_configure_input_channel(enum TimPeriph periph,
|
||||
enum TimChannel channel_mask, enum TimInputConfig config_mask,
|
||||
uint16_t value);
|
||||
void tim_configure_ext_trigger(enum TimPeriph periph,
|
||||
enum TimExtConfig ext_config_mask);
|
||||
|
||||
#endif //_TIM_H_
|
||||
|
||||
455
drv/tim_regs.h
Normal file
455
drv/tim_regs.h
Normal file
@ -0,0 +1,455 @@
|
||||
/** @file tim_regs.h
|
||||
* Module defining the TIMers registers.
|
||||
*
|
||||
* Mainly made to be used by the tim module. It is recommanded to go through
|
||||
* the functions provided by that module instead of directly using the registers
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef _TIM_REGS_H_
|
||||
#define _TIM_REGS_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define TIM1_BASE_ADDRESS 0x40012C00
|
||||
#define TIM2_BASE_ADDRESS 0x40000000
|
||||
#define TIM3_BASE_ADDRESS 0x40000400
|
||||
#define TIM4_BASE_ADDRESS 0x40000800
|
||||
|
||||
union TIM_CR1 {
|
||||
struct {
|
||||
uint32_t CEN:1;
|
||||
uint32_t UDIS:1;
|
||||
uint32_t URS:1;
|
||||
uint32_t OPM:1;
|
||||
uint32_t DIR:1;
|
||||
uint32_t CMS:2;
|
||||
uint32_t ARPE:1;
|
||||
uint32_t CKD:2;
|
||||
uint32_t reserved1:22;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CR2 {
|
||||
struct {
|
||||
uint32_t reserved1:3;
|
||||
uint32_t CCDS:1;
|
||||
uint32_t MMS:3;
|
||||
uint32_t TI1S:1;
|
||||
uint32_t reserved2:24;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_CR2 {
|
||||
struct {
|
||||
uint32_t CCPC:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t CCUS:1;
|
||||
uint32_t CCDS:1;
|
||||
uint32_t MMS:3;
|
||||
uint32_t TI1S:1;
|
||||
uint32_t OI1S:1;
|
||||
uint32_t OIS1N:1;
|
||||
uint32_t OIS2:1;
|
||||
uint32_t OIS2N:1;
|
||||
uint32_t OIS3:1;
|
||||
uint32_t OIS3N:1;
|
||||
uint32_t OIS4:1;
|
||||
uint32_t reserved2:17;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_SMCR {
|
||||
struct {
|
||||
uint32_t SMS:3;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t TS:3;
|
||||
uint32_t MSM:1;
|
||||
uint32_t ETF:4;
|
||||
uint32_t ETPS:2;
|
||||
uint32_t ECE:1;
|
||||
uint32_t ETP:1;
|
||||
uint32_t reserved2:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_DIER {
|
||||
struct {
|
||||
uint32_t UIE:1;
|
||||
uint32_t CC1IE:1;
|
||||
uint32_t CC2IE:1;
|
||||
uint32_t CC3IE:1;
|
||||
uint32_t CC4IE:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t TIE:1;
|
||||
uint32_t reserved2:1;
|
||||
uint32_t UDE:1;
|
||||
uint32_t CC1DE:1;
|
||||
uint32_t CC2DE:1;
|
||||
uint32_t CC3DE:1;
|
||||
uint32_t CC4DE:1;
|
||||
uint32_t COMDE:1;
|
||||
uint32_t TDE:1;
|
||||
uint32_t reserved3:17;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_DIER {
|
||||
struct {
|
||||
uint32_t UIE:1;
|
||||
uint32_t CC1IE:1;
|
||||
uint32_t CC2IE:1;
|
||||
uint32_t CC3IE:1;
|
||||
uint32_t CC4IE:1;
|
||||
uint32_t COMIE:1;
|
||||
uint32_t TIE:1;
|
||||
uint32_t BIE:1;
|
||||
uint32_t UDE:1;
|
||||
uint32_t CC1DE:1;
|
||||
uint32_t CC2DE:1;
|
||||
uint32_t CC3DE:1;
|
||||
uint32_t CC4DE:1;
|
||||
uint32_t COMDE:1;
|
||||
uint32_t TDE:1;
|
||||
uint32_t reserved1:17;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
|
||||
union TIM_SR {
|
||||
struct {
|
||||
uint32_t UIF:1;
|
||||
uint32_t CC1IF:1;
|
||||
uint32_t CC2IF:1;
|
||||
uint32_t CC3IF:1;
|
||||
uint32_t CC4IF:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t TIF:1;
|
||||
uint32_t reserved2:2;
|
||||
uint32_t CC1OF:1;
|
||||
uint32_t CC2OF:1;
|
||||
uint32_t CC3OF:1;
|
||||
uint32_t CC4OF:1;
|
||||
uint32_t reserved3:19;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_SR {
|
||||
struct {
|
||||
uint32_t UIF:1;
|
||||
uint32_t CC1IF:1;
|
||||
uint32_t CC2IF:1;
|
||||
uint32_t CC3IF:1;
|
||||
uint32_t CC4IF:1;
|
||||
uint32_t COMIF:1;
|
||||
uint32_t TIF:1;
|
||||
uint32_t BIF:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t CC1OF:1;
|
||||
uint32_t CC2OF:1;
|
||||
uint32_t CC3OF:1;
|
||||
uint32_t CC4OF:1;
|
||||
uint32_t reserved2:19;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_EGR {
|
||||
struct {
|
||||
uint32_t UG:1;
|
||||
uint32_t CC1G:1;
|
||||
uint32_t CC2G:1;
|
||||
uint32_t CC3G:1;
|
||||
uint32_t CC4G:1;
|
||||
uint32_t reserved1:1;
|
||||
uint32_t TG:1;
|
||||
uint32_t reserved2:25;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_EGR {
|
||||
struct {
|
||||
uint32_t UG:1;
|
||||
uint32_t CC1G:1;
|
||||
uint32_t CC2G:1;
|
||||
uint32_t CC3G:1;
|
||||
uint32_t CC4G:1;
|
||||
uint32_t COMG:1;
|
||||
uint32_t TG:1;
|
||||
uint32_t BG:1;
|
||||
uint32_t reserved1:24;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCMR1_INPUT {
|
||||
struct {
|
||||
uint32_t CC1S:2;
|
||||
uint32_t OC1FE:1;
|
||||
uint32_t OC1PE:1;
|
||||
uint32_t OC1M:3;
|
||||
uint32_t OC1CE:1;
|
||||
uint32_t CC2S:2;
|
||||
uint32_t OC2FE:1;
|
||||
uint32_t OC2PE:1;
|
||||
uint32_t OC2M:3;
|
||||
uint32_t OC2CE:1;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCMR1_OUTPUT {
|
||||
struct {
|
||||
uint32_t CC1S:2;
|
||||
uint32_t IC1PSC:2;
|
||||
uint32_t IC1F:4;
|
||||
uint32_t CC2S:2;
|
||||
uint32_t IC2PSC:2;
|
||||
uint32_t IC2F:4;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCMR1 {
|
||||
union TIM_CCMR1_INPUT input;
|
||||
union TIM_CCMR1_OUTPUT output;
|
||||
};
|
||||
|
||||
union TIM_CCMR2_INPUT {
|
||||
struct {
|
||||
uint32_t CC3S:2;
|
||||
uint32_t OC3FE:1;
|
||||
uint32_t OC3PE:1;
|
||||
uint32_t OC3M:3;
|
||||
uint32_t OC3CE:1;
|
||||
uint32_t CC4S:2;
|
||||
uint32_t OC4FE:1;
|
||||
uint32_t OC4PE:1;
|
||||
uint32_t OC4M:3;
|
||||
uint32_t OC4CE:1;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCMR2_OUTPUT {
|
||||
struct {
|
||||
uint32_t CC3S:2;
|
||||
uint32_t IC3PSC:2;
|
||||
uint32_t IC3F:4;
|
||||
uint32_t CC4S:2;
|
||||
uint32_t IC4PSC:2;
|
||||
uint32_t IC4F:4;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCMR2 {
|
||||
union TIM_CCMR2_INPUT input;
|
||||
union TIM_CCMR2_OUTPUT output;
|
||||
};
|
||||
|
||||
union TIM_CCER {
|
||||
struct {
|
||||
uint32_t CC1E:1;
|
||||
uint32_t CC1P:1;
|
||||
uint32_t reserved1:2;
|
||||
uint32_t CC2E:1;
|
||||
uint32_t CC2P:1;
|
||||
uint32_t reserved2:2;
|
||||
uint32_t CC3E:1;
|
||||
uint32_t CC3P:1;
|
||||
uint32_t reserved3:2;
|
||||
uint32_t CC4E:1;
|
||||
uint32_t CC4P:1;
|
||||
uint32_t reserved4:18;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_CCER {
|
||||
struct {
|
||||
uint32_t CC1E:1;
|
||||
uint32_t CC1P:1;
|
||||
uint32_t CC1NE:1;
|
||||
uint32_t CC1NP:1;
|
||||
uint32_t CC2E:1;
|
||||
uint32_t CC2P:1;
|
||||
uint32_t CC2NE:1;
|
||||
uint32_t CC2NP:1;
|
||||
uint32_t CC3E:1;
|
||||
uint32_t CC3P:1;
|
||||
uint32_t CC3NE:1;
|
||||
uint32_t CC3NP:1;
|
||||
uint32_t CC4E:1;
|
||||
uint32_t CC4P:1;
|
||||
uint32_t CC4NE:1;
|
||||
uint32_t CC4NP:1;
|
||||
uint32_t reserved1:18;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CNT {
|
||||
struct {
|
||||
uint32_t CNT:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_PSC {
|
||||
struct {
|
||||
uint32_t PSC:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ARR {
|
||||
struct {
|
||||
uint32_t ARR:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_RCR {
|
||||
struct {
|
||||
uint32_t REP:8;
|
||||
uint32_t reserved1:24;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCR1 {
|
||||
struct {
|
||||
uint32_t CCR1:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCR2 {
|
||||
struct {
|
||||
uint32_t CCR2:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCR3 {
|
||||
struct {
|
||||
uint32_t CCR3:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_CCR4 {
|
||||
struct {
|
||||
uint32_t CCR4:16;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_ADV_BDTR {
|
||||
struct {
|
||||
uint32_t DT:8;
|
||||
uint32_t LOCK:2;
|
||||
uint32_t OSSI:1;
|
||||
uint32_t OSSR:1;
|
||||
uint32_t BKE:1;
|
||||
uint32_t BKP:1;
|
||||
uint32_t AOE:1;
|
||||
uint32_t MOE:1;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_DCR {
|
||||
struct {
|
||||
uint32_t DBA:5;
|
||||
uint32_t reserved1:3;
|
||||
uint32_t MBL:5;
|
||||
uint32_t reserved2:19;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union TIM_DMAR {
|
||||
struct {
|
||||
uint32_t DMAB;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
struct TIM {
|
||||
union TIM_CR1 cr1;
|
||||
union TIM_CR2 cr2;
|
||||
union TIM_SMCR smcr;
|
||||
union TIM_DIER dier;
|
||||
union TIM_SR sr;
|
||||
union TIM_EGR egr;
|
||||
union TIM_CCMR1 ccmr1;
|
||||
union TIM_CCMR2 ccmr2;
|
||||
union TIM_CCER ccer;
|
||||
union TIM_CNT cnt;
|
||||
union TIM_PSC psc;
|
||||
union TIM_ARR arr;
|
||||
uint32_t reserved1;
|
||||
union TIM_CCR1 ccr1;
|
||||
union TIM_CCR2 ccr2;
|
||||
union TIM_CCR3 ccr3;
|
||||
union TIM_CCR4 ccr4;
|
||||
uint32_t reserved2;
|
||||
union TIM_DCR dcr;
|
||||
union TIM_DMAR dmar;
|
||||
};
|
||||
|
||||
struct TIM_ADV {
|
||||
union TIM_CR1 cr1;
|
||||
union TIM_ADV_CR2 cr2;
|
||||
union TIM_SMCR smcr;
|
||||
union TIM_ADV_DIER dier;
|
||||
union TIM_ADV_SR sr;
|
||||
union TIM_ADV_EGR egr;
|
||||
union TIM_CCMR1 ccmr1;
|
||||
union TIM_CCMR2 ccmr2;
|
||||
union TIM_ADV_CCER ccer;
|
||||
union TIM_CNT cnt;
|
||||
union TIM_PSC psc;
|
||||
union TIM_ARR arr;
|
||||
union TIM_ADV_RCR rcr;
|
||||
union TIM_CCR1 ccr1;
|
||||
union TIM_CCR2 ccr2;
|
||||
union TIM_CCR3 ccr3;
|
||||
union TIM_CCR4 ccr4;
|
||||
union TIM_ADV_BDTR bdtr;
|
||||
union TIM_DCR dcr;
|
||||
union TIM_DMAR dmar;
|
||||
};
|
||||
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
#endif //_TIM_REGS_H_
|
||||
|
||||
259
drv/usart.c
Normal file
259
drv/usart.c
Normal file
@ -0,0 +1,259 @@
|
||||
/** @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 "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) {
|
||||
usarts[periph]->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;
|
||||
}
|
||||
|
||||
usarts[periph]->CR3.DMAR = 1;
|
||||
return &usarts_rx_param[periph];
|
||||
}
|
||||
|
||||
const struct DmaParam* usart_configure_tx_dma(enum UsartPeriph periph)
|
||||
{
|
||||
if (periph > USART_PERIPH_3) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
usarts[periph]->CR3.DMAT = 1;
|
||||
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:
|
||||
regs->CR1.PCE = 1;
|
||||
regs->CR1.PS = 0;
|
||||
break;
|
||||
case USART_CONFIG_7O1:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8O1:
|
||||
case USART_CONFIG_8O2:
|
||||
regs->CR1.PCE = 1;
|
||||
regs->CR1.PS = 1;
|
||||
break;
|
||||
case USART_CONFIG_8N1:
|
||||
case USART_CONFIG_8N2:
|
||||
regs->CR1.PCE = 0;
|
||||
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:
|
||||
regs->CR1.M = 0;
|
||||
break;
|
||||
case USART_CONFIG_8E2:
|
||||
case USART_CONFIG_8E1:
|
||||
case USART_CONFIG_8O1:
|
||||
case USART_CONFIG_8O2:
|
||||
regs->CR1.M = 1;
|
||||
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:
|
||||
regs->CR2.STOP = 0;
|
||||
break;
|
||||
case USART_CONFIG_7E2:
|
||||
case USART_CONFIG_7O2:
|
||||
case USART_CONFIG_8N2:
|
||||
case USART_CONFIG_8E2:
|
||||
case USART_CONFIG_8O2:
|
||||
regs->CR2.STOP = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//enable Rx/Tx
|
||||
regs->CR1.TE = 1;
|
||||
regs->CR1.RE = 1;
|
||||
regs->CR1.UE = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
regs->BRR.DIV_Mantissa = mantissa & 0xFFF;
|
||||
regs->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_
|
||||
|
||||
137
drv/usart_regs.h
Normal file
137
drv/usart_regs.h
Normal file
@ -0,0 +1,137 @@
|
||||
/** @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 "stdint.h"
|
||||
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
#define USART1_BASE_ADDRESS 0x40013800
|
||||
#define USART2_BASE_ADDRESS 0x40004400
|
||||
#define USART3_BASE_ADDRESS 0x40004800
|
||||
|
||||
union USART_SR {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union USART_DR {
|
||||
struct {
|
||||
uint32_t DR:9;
|
||||
uint32_t reserved1:23;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union USART_BRR {
|
||||
struct {
|
||||
uint32_t DIV_Fraction:4;
|
||||
uint32_t DIV_Mantissa:12;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
union USART_CR1 {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union USART_CR2 {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union USART_CR3 {
|
||||
struct {
|
||||
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;
|
||||
};
|
||||
|
||||
union USART_GTPR {
|
||||
struct {
|
||||
uint32_t PSC:8;
|
||||
uint32_t GT:8;
|
||||
uint32_t reserved1:16;
|
||||
};
|
||||
uint32_t word;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
25
openocd.cfg
Normal file
25
openocd.cfg
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
# using a STM32f103CB wich has 128kB of flash instead of the more common 64KB
|
||||
set CHIPNAME stm32f103CB
|
||||
set FLASH_SIZE 0x20000
|
||||
|
||||
# load default configurations
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/stm32f1x.cfg]
|
||||
|
||||
# override examine-end event
|
||||
$CHIPNAME.cpu configure -event examine-end {
|
||||
# write DBGMCU_CR, disable all peripherals (timers, dmas, watchdogs while
|
||||
# halted by debug. Trace is not affected
|
||||
mmw 0xE0042004 0x7E3FFF07 0
|
||||
}
|
||||
|
||||
|
||||
reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
# inits debugging, from that point, commands can be used
|
||||
init
|
||||
# resets the target and halt it immediately afterward. Stops debug from being
|
||||
# inacessible due to low-power states
|
||||
reset halt
|
||||
|
||||
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("");
|
||||
debug_trace("------------------------------------------------------------------------------");
|
||||
debug_trace("starting debug software");
|
||||
debug_trace("compiled on " __DATE__ " at " __TIME__);
|
||||
debug_trace("------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
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_
|
||||
|
||||
23
srv/delay.c
Normal file
23
srv/delay.c
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file delay.c
|
||||
* Module handling delays definitions and operations
|
||||
*
|
||||
* The module provides an API to delay the code execution with the most
|
||||
* accuraccy possible, putting the system in sleep whenever possible. The RTC is
|
||||
* required when using delays superior to a 1.5s. Accuraccy is only garenteed up
|
||||
* to the unit being used (to the millisecond when delaying in ms, to the second
|
||||
* when delaying in seconds)
|
||||
*/
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
#include "delay.h"
|
||||
|
||||
|
||||
//--local definitions-----------------------------------------------------------
|
||||
|
||||
//--local variables-------------------------------------------------------------
|
||||
|
||||
//--public functions------------------------------------------------------------
|
||||
|
||||
//--local functions-------------------------------------------------------------
|
||||
|
||||
23
srv/delay.h
Normal file
23
srv/delay.h
Normal file
@ -0,0 +1,23 @@
|
||||
/** @file delay.h
|
||||
* Module handling delays definitions and operations
|
||||
*
|
||||
* The module provides an API to delay the code execution with the most
|
||||
* accuraccy possible, putting the system in sleep whenever possible. The RTC is
|
||||
* required when using delays superior to a 1.5s. Accuraccy is only garenteed up
|
||||
* to the unit being used (to the millisecond when delaying in ms, to the second
|
||||
* when delaying in seconds)
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H_
|
||||
#define _DELAY_H_
|
||||
|
||||
//--includes--------------------------------------------------------------------
|
||||
|
||||
//--type definitions------------------------------------------------------------
|
||||
|
||||
//--functions-------------------------------------------------------------------
|
||||
|
||||
//--internal_functions----------------------------------------------------------
|
||||
|
||||
#endif //_DELAY_H_
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user