mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-26 12:14:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32406b678b | ||
|
|
55e2077a46 | ||
|
|
a771d6a19d | ||
|
|
0d5d7bb26f | ||
|
|
3808dd3222 | ||
|
|
8fc94e12af | ||
|
|
824e33ef8a | ||
|
|
655f9a9f79 | ||
|
|
6ac6aa521c | ||
|
|
3982e065c8 | ||
|
|
497b8027f5 | ||
|
|
89757388c7 | ||
|
|
77fae5c562 | ||
|
|
80fcba91c8 | ||
|
|
39d64be581 | ||
|
|
2bfd30ab4b | ||
|
|
60004eb209 | ||
|
|
db11897d71 | ||
|
|
5e466f9037 | ||
|
|
6b2698a503 | ||
|
|
4788db7e00 | ||
|
|
d9680df510 | ||
|
|
f20ee1f305 | ||
|
|
302bf865f9 | ||
|
|
03929dcdaa | ||
|
|
89af2e9638 | ||
|
|
015586950f | ||
|
|
9df261a0eb | ||
|
|
a2a3c84450 | ||
|
|
6611348ebf | ||
|
|
e69ee90acf | ||
|
|
8f3554d08a | ||
|
|
b6ee9e637b | ||
|
|
f46453f80f | ||
|
|
3deafaea7f | ||
|
|
a15d518571 | ||
|
|
886a29d659 | ||
|
|
e69de57def | ||
|
|
9d68e20dcc | ||
|
|
c0a8546330 | ||
|
|
4c0002e28a | ||
|
|
7c37d75bf4 | ||
|
|
879261981f | ||
|
|
838b0bcd27 | ||
|
|
736b8ad7b7 | ||
|
|
db27fae40e | ||
|
|
594111a255 | ||
|
|
53a46a2739 | ||
|
|
eef7a55904 | ||
|
|
a68fa5e6e0 | ||
|
|
7c0d126edc | ||
|
|
1a5e3d3151 | ||
|
|
95ff6c56af | ||
|
|
e2ef392633 | ||
|
|
dbc2356768 | ||
|
|
47e5e984df | ||
|
|
0f32f50c50 | ||
|
|
606cc1f538 | ||
|
|
2bb11888d5 | ||
|
|
09b1d6aa72 | ||
|
|
72f0489ec2 | ||
|
|
7b39973065 | ||
|
|
30b64483fd | ||
|
|
5369fb0376 | ||
|
|
5fe34fd6c3 | ||
|
|
0fbdda4d2e | ||
|
|
a98e980c8f | ||
|
|
2b836504ab | ||
|
|
0de3f0d985 | ||
|
|
151e375091 | ||
|
|
c44549bfa5 | ||
|
|
d6852f5e74 | ||
|
|
9173034b96 | ||
|
|
2888ab1f52 | ||
|
|
26b5416641 | ||
|
|
8bcac7e955 | ||
|
|
ea25e8129c | ||
|
|
26cb44f9d9 | ||
|
|
7a37a44433 | ||
|
|
a752f3f8c7 | ||
|
|
946e07644c | ||
|
|
497b26a249 | ||
|
|
79aad7fabf | ||
|
|
7851930ac3 | ||
|
|
758572872d | ||
|
|
111551477a | ||
|
|
31c9e3fb7e | ||
|
|
7061b7202f | ||
|
|
d88b6a3c95 | ||
|
|
cea2a62ee0 | ||
|
|
35a8b8e8e8 | ||
|
|
1b8624f135 | ||
|
|
e217066bf6 | ||
|
|
5430408218 | ||
|
|
d2744063a0 | ||
|
|
03356616ef | ||
|
|
6ce2e48dd3 | ||
|
|
16a7ba6bf0 | ||
|
|
e9d122f231 | ||
|
|
0ae5c61759 | ||
|
|
691460c5fc | ||
|
|
ab1c924388 | ||
|
|
05050eba38 | ||
|
|
912dd518bf | ||
|
|
e0395a9907 | ||
|
|
0051f23e12 | ||
|
|
a9bb8fa9fc | ||
|
|
09f5d2fdae | ||
|
|
006a9d914c | ||
|
|
9009cbc528 | ||
|
|
a1862986b8 | ||
|
|
cc2989a848 | ||
|
|
4deb95776f | ||
|
|
f195b27884 | ||
|
|
5036a71334 | ||
|
|
531c47b47c | ||
|
|
4dbb2da78f | ||
|
|
41c1e0f08d | ||
|
|
e7b1905e49 | ||
|
|
e00265f855 | ||
|
|
cd36708b6d | ||
|
|
5bd22cb5e4 | ||
|
|
bc00d5159a | ||
|
|
bcb0874477 | ||
|
|
5326e8d212 | ||
|
|
4528cc28ef | ||
|
|
381d7cce54 | ||
|
|
2594e7b37a | ||
|
|
4356b953ca | ||
|
|
e788853156 | ||
|
|
91ed6de166 | ||
|
|
cf3aafc32e | ||
|
|
c2d7ff8179 | ||
|
|
e5eaa1c633 | ||
|
|
6366c832b0 | ||
|
|
f326cbedbe | ||
|
|
5b272c2b5c |
No files matched your search
@@ -0,0 +1,11 @@
|
|||||||
|
- My goal is: _describe_
|
||||||
|
- My actions were: _describe_
|
||||||
|
- My expectation was: _describe_
|
||||||
|
- The result I saw: _provide logs or description_
|
||||||
|
- My question is: _your question_
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
|
||||||
|
- mongoose version: _X.Y_
|
||||||
|
- OS: _?_
|
||||||
|
- Compiler/IDE: _?_
|
||||||
@@ -11,6 +11,12 @@ jobs:
|
|||||||
run: make test test++ IPV6=0
|
run: make test test++ IPV6=0
|
||||||
- name: openssl
|
- name: openssl
|
||||||
run: make test SSL=OPENSSL IPV6=0
|
run: make test SSL=OPENSSL IPV6=0
|
||||||
|
examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: sudo apt-get install libmbedtls-dev
|
||||||
- name: examples
|
- name: examples
|
||||||
run: make ex
|
run: make ex
|
||||||
macos:
|
macos:
|
||||||
@@ -22,7 +28,7 @@ jobs:
|
|||||||
- name: make
|
- name: make
|
||||||
run: make test++ upload-coverage IPV6=0
|
run: make test++ upload-coverage IPV6=0
|
||||||
- name: openssl
|
- name: openssl
|
||||||
run: make test SSL=OPENSSL IPV6=0
|
run: make test SSL=OPENSSL IPV6=0 OPENSSL=`echo /usr/local/Cellar/openssl*/*`
|
||||||
- name: exports
|
- name: exports
|
||||||
run: make mg_prefix
|
run: make mg_prefix
|
||||||
windows:
|
windows:
|
||||||
@@ -37,4 +43,9 @@ jobs:
|
|||||||
run: make mingw
|
run: make mingw
|
||||||
- name: mingw++
|
- name: mingw++
|
||||||
run: make mingw++
|
run: make mingw++
|
||||||
|
arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: arm
|
||||||
|
run: make arm
|
||||||
@@ -1,33 +1,35 @@
|
|||||||
SRCS = $(wildcard src/*.c)
|
SRCS = $(wildcard src/*.c)
|
||||||
HDRS = $(wildcard src/*.h)
|
HDRS = $(wildcard src/*.h)
|
||||||
DEFS ?= -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
|
DEFS ?= -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
|
||||||
CFLAGS ?= -W -Wall -Werror -Isrc -I. -O0 -g $(DEFS) $(TFLAGS) $(EXTRA)
|
WARN ?= -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion
|
||||||
|
OPTS ?= -O3 -g3
|
||||||
|
INCS ?= -Isrc -I.
|
||||||
|
CFLAGS ?= $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) $(EXTRA)
|
||||||
SSL ?= MBEDTLS
|
SSL ?= MBEDTLS
|
||||||
CDIR ?= $(realpath $(CURDIR))
|
CDIR ?= $(realpath $(CURDIR))
|
||||||
VC98 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc98
|
VC98 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc98
|
||||||
VC2017 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc2017
|
VC2017 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc2017
|
||||||
MINGW = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/mingw
|
MINGW = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/mingw
|
||||||
GCC = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/cc2
|
GCC = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/cc2
|
||||||
|
ARM = docker run -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/armgcc
|
||||||
VCFLAGS = /nologo /W3 /O2 /I. $(DEFS) $(TFLAGS)
|
VCFLAGS = /nologo /W3 /O2 /I. $(DEFS) $(TFLAGS)
|
||||||
CLANG ?= clang # /usr/local/opt/llvm\@9/bin/clang
|
CLANG ?= clang # /usr/local/opt/llvm\@9/bin/clang
|
||||||
IPV6 ?= 1
|
IPV6 ?= 1
|
||||||
ASAN_OPTIONS ?=
|
ASAN_OPTIONS ?=
|
||||||
EXAMPLES := $(wildcard examples/*)
|
EXAMPLES := $(wildcard examples/*)
|
||||||
EXAMPLE_TARGET ?= example
|
EXAMPLE_TARGET ?= example
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
SOVERSION = 7.2
|
||||||
.PHONY: ex test
|
.PHONY: ex test
|
||||||
|
|
||||||
ifeq "$(SSL)" "MBEDTLS"
|
ifeq "$(SSL)" "MBEDTLS"
|
||||||
MBEDTLS_DIR ?= $(shell brew --cellar mbedtls)
|
MBEDTLS ?= /usr
|
||||||
MBEDTLS_VER ?= $(shell brew info mbedtls --json | jq -j .[0].installed[0].version)
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
||||||
MBEDTLS ?= $(MBEDTLS_DIR)/$(MBEDTLS_VER)
|
|
||||||
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
|
||||||
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
endif
|
endif
|
||||||
ifeq "$(SSL)" "OPENSSL"
|
ifeq "$(SSL)" "OPENSSL"
|
||||||
OPENSSL_DIR ?= $(shell brew --cellar openssl)
|
OPENSSL ?= /usr
|
||||||
OPENSSL_VER ?= $(shell brew info openssl --json | jq -j .[0].installed[0].version)
|
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
|
||||||
OPENSSL ?= $(OPENSSL_DIR)/$(OPENSSL_VER)
|
|
||||||
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
|
|
||||||
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
|
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -41,13 +43,13 @@ mg_prefix: mongoose.c mongoose.h
|
|||||||
$(CLANG) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T' | grep -v 'mg_' ; test $$? = 1
|
$(CLANG) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T' | grep -v 'mg_' ; test $$? = 1
|
||||||
|
|
||||||
# C++ build
|
# C++ build
|
||||||
test++: CLANG = g++ -Wno-deprecated -Wno-missing-field-initializers
|
test++: CLANG = g++
|
||||||
test++: unamalgamated
|
test++: WARN += -Wno-shadow -Wno-missing-field-initializers -Wno-deprecated
|
||||||
|
test++: test
|
||||||
|
|
||||||
# Make sure we can build from an unamalgamated sources
|
# Make sure we can build from an unamalgamated sources
|
||||||
unamalgamated: $(SRCS) $(HDRS) Makefile
|
unamalgamated: $(SRCS) $(HDRS) Makefile
|
||||||
$(CLANG) src/*.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
$(CLANG) src/*.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
||||||
|
|
||||||
fuzz: mongoose.c mongoose.h Makefile test/fuzz.c
|
fuzz: mongoose.c mongoose.h Makefile test/fuzz.c
|
||||||
$(CLANG) mongoose.c test/fuzz.c $(CFLAGS) -DMG_ENABLE_LINES -DMG_ENABLE_LOG=0 -fsanitize=fuzzer,signed-integer-overflow,address $(LDFLAGS) -g -o fuzzer
|
$(CLANG) mongoose.c test/fuzz.c $(CFLAGS) -DMG_ENABLE_LINES -DMG_ENABLE_LOG=0 -fsanitize=fuzzer,signed-integer-overflow,address $(LDFLAGS) -g -o fuzzer
|
||||||
$(DEBUGGER) ./fuzzer
|
$(DEBUGGER) ./fuzzer
|
||||||
@@ -92,14 +94,31 @@ linux: Makefile mongoose.c mongoose.h test/unit_test.c
|
|||||||
$(GCC) $(CC) mongoose.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -o unit_test_gcc
|
$(GCC) $(CC) mongoose.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -o unit_test_gcc
|
||||||
$(GCC) ./unit_test_gcc
|
$(GCC) ./unit_test_gcc
|
||||||
|
|
||||||
linux++: CC = g++ -Wno-missing-field-initializers
|
linux++: CC = g++
|
||||||
|
linux++: WARN += -Wno-missing-field-initializers
|
||||||
linux++: linux
|
linux++: linux
|
||||||
|
|
||||||
|
linux-libs: CFLAGS += -fPIC
|
||||||
|
linux-libs: mongoose.o
|
||||||
|
$(CC) mongoose.o $(LDFLAGS) -shared -o libmongoose.so.$(SOVERSION)
|
||||||
|
$(AR) rcs libmongoose.a mongoose.o
|
||||||
|
|
||||||
|
install: linux-libs
|
||||||
|
install -Dm644 libmongoose.a libmongoose.so.$(SOVERSION) $(DESTDIR)$(PREFIX)/lib
|
||||||
|
ln -s libmongoose.so.$(SOVERSION) $(DESTDIR)$(PREFIX)/lib/libmongoose.so
|
||||||
|
install -Dm644 mongoose.h $(DESTDIR)$(PREFIX)/include/mongoose.h
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -rf $(DESTDIR)$(PREFIX)/lib/libmongoose.a $(DESTDIR)$(PREFIX)/lib/libmongoose.so.$(SOVERSION) $(DESTDIR)$(PREFIX)/include/mongoose.h $(DESTDIR)$(PREFIX)/lib/libmongoose.so
|
||||||
|
|
||||||
|
arm: Makefile mongoose.c mongoose.h test/unit_test.c
|
||||||
|
$(ARM) arm-none-eabi-gcc mongoose.c -c -Itest -DMG_ARCH=MG_ARCH_CUSTOM $(OPTS) $(WARN) $(INCS) -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_DIRECTORY_LISTING=0 -DMG_ENABLE_SSI=1
|
||||||
|
|
||||||
mongoose.c: $(SRCS) Makefile
|
mongoose.c: $(SRCS) Makefile
|
||||||
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/private.h src/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/private.h src/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
||||||
|
|
||||||
mongoose.h: $(HDRS) Makefile
|
mongoose.h: $(HDRS) Makefile
|
||||||
(cat src/license.h src/version.h ; cat src/arch.h src/arch_*.h src/config.h src/str.h src/log.h src/timer.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/ws.h src/sntp.h src/mqtt.h src/dns.h | sed -e 's,#include ".*,,' -e 's,^#pragma once,,')> $@
|
(cat src/license.h src/version.h ; cat src/arch.h src/arch_*.h src/config.h src/str.h src/log.h src/timer.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/ws.h src/sntp.h src/mqtt.h src/dns.h | sed -e 's,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
||||||
|
|
||||||
clean: EXAMPLE_TARGET = clean
|
clean: EXAMPLE_TARGET = clean
|
||||||
clean: ex
|
clean: ex
|
||||||
|
|||||||
@@ -1,75 +1,93 @@
|
|||||||
# Mongoose - Embedded Web Server / Embedded Networking Library
|
# Mongoose - Embedded Web Server / Embedded Networking Library
|
||||||
|
|
||||||

|
[](https://opensource.org/licenses/gpl-2.0.php)
|
||||||
[](https://github.com/cesanta/mongoose/actions)
|
[](https://github.com/cesanta/mongoose/actions)
|
||||||
[](https://codecov.io/gh/cesanta/mongoose)
|
[](https://codecov.io/gh/cesanta/mongoose)
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
||||||
|
|
||||||
Mongoose is a networking library for C/C++. It implements event-driven
|
Mongoose is a networking library for C/C++. It implements event-driven
|
||||||
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It has been designed
|
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It is designed for
|
||||||
for connecting devices and bringing them online. On the market since 2004, used
|
connecting devices and bringing them online. On the market since 2004, used by
|
||||||
by vast number of open source and commercial products - it even runs on the
|
vast number of open source and commercial products - it even runs on the
|
||||||
International Space Station! Mongoose makes embedded network programming fast,
|
International Space Station! Mongoose makes embedded network programming fast,
|
||||||
robust, and easy.
|
robust, and easy. Features include:
|
||||||
|
|
||||||
- [Download Mongoose Source Code here](https://www.cesanta.com/download.html)
|
- Cross-platform: works on Linux/UNIX, MacOS, Windows, Android, FreeRTOS, etc.
|
||||||
- [Read Mongoose documentation](https://cesanta.com/docs/)
|
- Supported embedded architectures: ESP32, NRF52, STM32, NXP, and more
|
||||||
|
- Built-in protocols: plain TCP/UDP, HTTP, MQTT, Websocket
|
||||||
|
- SSL/TLS support: mbedTLS, OpenSSL or custom (via API)
|
||||||
|
- Asynchronous DNS resolver
|
||||||
|
- Tiny static and run-time footprint
|
||||||
|
- Source code is both ISO C and ISO C++ compliant
|
||||||
|
- Works with any network stack with socket API, like LwIP or FreeRTOS-Plus-TCP
|
||||||
|
- Very easy to integrate: just copy `mongoose.c` and `mongoose.h` files to your build tree
|
||||||
|
- Detailed [documentation](https://cesanta.com/docs/)
|
||||||
|
|
||||||
Connectivity is vital for software and embedded devices, but there are many
|
|
||||||
pitfalls to consider when embedding a web server. This white paper breaks down
|
|
||||||
on the top 9 things to avoid when embedding a web server.
|
|
||||||
|
|
||||||
- [Download “9 Things NOT to do when embedding a web server” white paper here](https://www.cesanta.com/whitepaper.html)
|
# Commercial use
|
||||||
|
- Mongoose is used by hundreds of businesses, from Fortune500 giants like
|
||||||
|
Siemens, Schneider Electric, Broadcom, Bosch, Google, Samsung, Qualcomm, Caterpillar to the small businesses
|
||||||
|
- Used to solve a wide range of business needs, like implementing Web UI
|
||||||
|
interface on devices, RESTful API services, telemetry data exchange, remote
|
||||||
|
control for a product, remote software updates, remote monitoring, and others
|
||||||
|
- Deployed to hundreds of millions devices in production environment worldwide
|
||||||
|
- See [Case Studies](https://cesanta.com/case-studies.html) from our respected
|
||||||
|
customers like Schneider Electric (industrial automation), Broadcom (semiconductors), Schenck Process
|
||||||
|
(industrial engineering), and others
|
||||||
|
- See [Testimonials](https://cesanta.com/testimonials.html) from engineers that
|
||||||
|
integrated Mongoose in their commercial products
|
||||||
|
- We provide [commercial licensing](https://cesanta.com/licensing.html),
|
||||||
|
[support](https://cesanta.com/support.html), consultancy and integration
|
||||||
|
assistance - don't hesitate to
|
||||||
|
[contact us](https://www.cesanta.com/contact.html)
|
||||||
|
|
||||||
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
|
|
||||||
- [Download pre-compiled Mongoose web server binary](https://mongoose.ws/)
|
|
||||||
|
|
||||||
# Looking for a complete IoT solution? Check out
|
# Security
|
||||||
- [VCON](https://vcon.io) - Arduino compatible MCU modules with built-in firmware OTA updates
|
|
||||||
- [Mongoose OS](https://mongoose-os.com) - open source embedded operating system for low-power connected microcontrollers. Secure, designed for commercial Internet of Things products
|
|
||||||
|
|
||||||
# Support
|
We take security seriously:
|
||||||
- [Study Mongoose examples](https://github.com/cesanta/mongoose/tree/master/examples)
|
1. Mongoose repository runs a
|
||||||
- [Support Forum - ask your technical questions here](https://forum.cesanta.com/c/mongoose-library/6)
|
[continuous integration test powered by GitHub](https://github.com/cesanta/mongoose/actions),
|
||||||
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
|
which runs through hundreds of unit tests on every commit to the repository.
|
||||||
- [Check out latest releases](https://github.com/cesanta/mongoose/releases)
|
Our [unit tests](https://github.com/cesanta/mongoose/tree/master/test)
|
||||||
|
are built with modern address sanitizer technologies, which help to find
|
||||||
|
security vulnerabilities early
|
||||||
|
2. Mongoose repository is integrated into Google's
|
||||||
|
[oss-fuzz continuous fuzzer](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
||||||
|
which scans for potential vulnerabilities continuously
|
||||||
|
3. We receive periodic vulnerability reports from the independent security
|
||||||
|
groups like
|
||||||
|
[Cisco Talos](https://www.cisco.com/c/en/us/products/security/talos.html),
|
||||||
|
[Microsoft Security Response Center](https://www.microsoft.com/en-us/msrc),
|
||||||
|
[MITRE Corporation](https://www.mitre.org/),
|
||||||
|
[Compass Security](https://www.compass-security.com/en/) and others.
|
||||||
|
In case of the vulnerability found, we act according to the industry best
|
||||||
|
practice: hold on to the publication, fix the software and notify all our
|
||||||
|
customers that have an appropriate subscription
|
||||||
|
4. Some of our customers (for example NASA)
|
||||||
|
have specific security requirements and run independent security audits,
|
||||||
|
of which we get notified and in case of any issue, act similar to (3).
|
||||||
|
|
||||||
# Features
|
# Supplement software
|
||||||
|
|
||||||
* Cross-platform: works on Linux/UNIX, MacOS, Windows, Android, FreeRTOS, etc
|
This software is often used together with Mongoose:
|
||||||
* Supported embedded architectures: ESP32, ESP8266, TI, NRF52, STM32, PIC32, NXP, and more
|
- [mjson](https://github.com/cesanta/mjson) - a JSON parser. Used to implement
|
||||||
* Builtin protocols: plain TCP/UDP, HTTP, MQTT, Websocket
|
RESTful APIs that use JSON, or implement data exchange (e.g. over MQTT
|
||||||
* SSL/TLS support: mbedTLS, OpenSSL or custom (via API)
|
or Websocket) that use JSON for data encapsulation
|
||||||
* Asynchronous DNS resolver
|
- [elk](https://github.com/cesanta/elk) - a tiny JavaScript interpreter.
|
||||||
* Tiny static and run-time footprint
|
Used to implement scripting support for customers
|
||||||
* Source code is both ISO C and ISO C++ compliant
|
|
||||||
* Very easy to integrate: just copy
|
|
||||||
[mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and
|
|
||||||
[mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h)
|
|
||||||
files to your build tree
|
|
||||||
|
|
||||||
# Licensing
|
|
||||||
|
|
||||||
Mongoose is released under Commercial and [GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open source licenses.
|
# Precompiled web server binary
|
||||||
|
|
||||||
Commercial Projects: [Contact us for commercial license.](https://www.cesanta.com/contact.html)
|
We have built a ready-to-go, precompiled web server binary for Windows
|
||||||
|
and Mac. It is a great tool for sharing your files or website. It has
|
||||||
|
a unique feature - an ability to share your local files via a global URL.
|
||||||
|
|
||||||
# Dashboard Example
|
Interested? Go to [download](https://mongoose.ws/)
|
||||||
|
|
||||||
Mongoose is often used to implement device dashboards and real-time
|
|
||||||
data exchange over Websocket. Here is a dashboard example that illustrates
|
|
||||||
the functionality:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[Developing a new product? Contact us today to discuss how Mongoose can help.](https://www.cesanta.com/contact.html)
|
|
||||||
|
|
||||||
# Contributions
|
# Contributions
|
||||||
|
|
||||||
Contributions are welcome! Please follow the guidelines below:
|
Contributions are welcome! Please follow the guidelines below:
|
||||||
|
|
||||||
- Sign [Cesanta CLA](https://cesanta.com/cla.html) and send GitHub pull request
|
- Sign [Cesanta CLA](https://cesanta.com/cla.html) and send GitHub pull request
|
||||||
- When making pull requests, please make sure that it has only one commit,
|
- Make sure that PRs have only one commit, and deal with one issue only
|
||||||
and imlements/fixes only one piece of functionality
|
|
||||||
|
|
||||||
|
|
||||||
+125
-79
@@ -6,24 +6,23 @@
|
|||||||
Mongoose is a networking library for C/C++. It implements an event-driven,
|
Mongoose is a networking library for C/C++. It implements an event-driven,
|
||||||
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It has been designed
|
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It has been designed
|
||||||
for connecting devices and bringing them online. On the market since 2004, used
|
for connecting devices and bringing them online. On the market since 2004, used
|
||||||
by vast number of open source and commercial products - it even runs on the
|
by a vast number of open source and commercial products - it even runs on the
|
||||||
International Space Station! Mongoose makes embedded network programming fast,
|
International Space Station! Mongoose makes embedded network programming fast,
|
||||||
robust, and easy.
|
robust, and easy.
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Cross-platform: works on Linux/UNIX, MacOS, QNX, eCos, Windows, Android,
|
* Works on Linux/UNIX, MacOS, Windows, QNX, eCos, Android and other
|
||||||
iPhone, FreeRTOS, etc
|
* Works on embedded hardware: STM32, ESP32, NXP, Xilinx, and other
|
||||||
* Supported hardware platforms: TI CC3200, TI MSP432, NRF52, STM32, PIC32, ESP8266, ESP32 and more
|
* Built-in protocols:
|
||||||
* Builtin protocols:
|
|
||||||
- plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way)
|
- plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way)
|
||||||
- HTTP client, HTTP server
|
- HTTP client, HTTP server
|
||||||
- WebSocket client, WebSocket server
|
- WebSocket client, WebSocket server
|
||||||
- MQTT client
|
- MQTT client, MQTT server
|
||||||
- DNS client, async DNS resolver
|
- DNS client, async DNS resolver
|
||||||
* Single-threaded, asynchronous, non-blocking core with simple event-based API
|
* Single-threaded, asynchronous, non-blocking core with simple event-based API
|
||||||
* Native support for [LWIP embedded TCP/IP stack](https://en.wikipedia.org/wiki/LwIP)
|
* Support for LWIP and FreeRTOS-Plus-TCP stacks
|
||||||
* Tiny static and run-time footprint
|
* Tiny static and run-time footprint
|
||||||
* Source code is both ISO C and ISO C++ compliant
|
* Source code is both ISO C and ISO C++ compliant
|
||||||
* Very easy to integrate: just copy
|
* Very easy to integrate: just copy
|
||||||
@@ -50,7 +49,7 @@ Mongoose's internals.
|
|||||||
An application that uses mongoose should follow a standard pattern of
|
An application that uses mongoose should follow a standard pattern of
|
||||||
event-driven application:
|
event-driven application:
|
||||||
|
|
||||||
1. Declare and initialise an event manager:
|
1. Declare and initialize an event manager:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
struct mg_mgr mgr;
|
struct mg_mgr mgr;
|
||||||
@@ -90,7 +89,7 @@ Each connection has a send and receive buffer:
|
|||||||
- `struct mg_connection::recv` - data received from a peer
|
- `struct mg_connection::recv` - data received from a peer
|
||||||
|
|
||||||
When data arrives, Mongoose appends received data to the `recv` and triggers an
|
When data arrives, Mongoose appends received data to the `recv` and triggers an
|
||||||
`MG_EV_RECV` event. The user may send data back by calling one of the output
|
`MG_EV_READ` event. The user may send data back by calling one of the output
|
||||||
functions, like `mg_send()` or `mg_printf()`. Output functions append data to
|
functions, like `mg_send()` or `mg_printf()`. Output functions append data to
|
||||||
the `send` buffer. When Mongoose successfully writes data to the socket, it
|
the `send` buffer. When Mongoose successfully writes data to the socket, it
|
||||||
discards data from struct `mg_connection::send` and sends an `MG_EV_SEND`
|
discards data from struct `mg_connection::send` and sends an `MG_EV_SEND`
|
||||||
@@ -106,7 +105,7 @@ what an event handler function looks like:
|
|||||||
```c
|
```c
|
||||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
/* Event handler code that defines behavior of the connection */
|
/* Event handler code that defines behaviour of the connection */
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,9 +113,9 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
|
|
||||||
- `struct mg_connection *c` - a connection that received an event
|
- `struct mg_connection *c` - a connection that received an event
|
||||||
- `int ev` - an event number, defined in mongoose.h. For example, when data
|
- `int ev` - an event number, defined in mongoose.h. For example, when data
|
||||||
arrives on an inbound connection, ev would be `MG_EV_RECV`
|
arrives on an inbound connection, ev would be `MG_EV_READ`
|
||||||
- `void *ev_data` - points to the event-specific data, and it has a different
|
- `void *ev_data` - points to the event-specific data, and it has a different
|
||||||
meaning for different events. For example, for an `MG_EV_RECV` event,
|
meaning for different events. For example, for an `MG_EV_READ` event,
|
||||||
`ev_data`
|
`ev_data`
|
||||||
is an `int *` pointing to the number of bytes received from a remote
|
is an `int *` pointing to the number of bytes received from a remote
|
||||||
peer and saved into the `c->recv` IO buffer. The exact meaning of `ev_data` is
|
peer and saved into the `c->recv` IO buffer. The exact meaning of `ev_data` is
|
||||||
@@ -127,7 +126,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
Below is the list of events trigged by Mongoose, taken as-is from `mongoose.h`.
|
Below is the list of events triggered by Mongoose, taken as-is from `mongoose.h`.
|
||||||
For each event, a comment describes a meaning of the `ev_data` pointer passed
|
For each event, a comment describes a meaning of the `ev_data` pointer passed
|
||||||
to an event handler:
|
to an event handler:
|
||||||
|
|
||||||
@@ -193,41 +192,62 @@ Mongoose source code ships in two files:
|
|||||||
- [mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) - implementation
|
- [mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) - implementation
|
||||||
|
|
||||||
Therefore to integrate Mongoose into an application, simply copy these two
|
Therefore to integrate Mongoose into an application, simply copy these two
|
||||||
files to the application's source tree.
|
files to the application's source tree. The `mongoose.c` and `mongoose.h` files
|
||||||
|
are, actually, an amalgamation - a non-amalgamated sources can be found at
|
||||||
|
https://github.com/cesanta/mongoose/tree/master/src
|
||||||
|
|
||||||
The `mongoose.c` and `mongoose.h` files are, actually, an amalgamation -
|
Mongoose have two types of build constants (preprocessor definitions) that
|
||||||
a non-amalgamated sources can be found at https://github.com/cesanta/mongoose/tree/master/src
|
affect the build: a target architecture, and tunables. In order to set the
|
||||||
|
option during build time, use the `-D OPTION` compiler flag:
|
||||||
Mongoose source code uses a bunch of build constants defined at
|
|
||||||
https://github.com/cesanta/mongoose/blob/master/src/config.h, together with
|
|
||||||
their default values.
|
|
||||||
|
|
||||||
In order to change the constant during build time, use the `-D
|
|
||||||
<PREPROCESSOR_FLAG>` compiler option. For example, to disable both MQTT,
|
|
||||||
compile the application `my_app.c` like this (assumed UNIX system):
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ cc my_app.c mongoose.c -D MG_MQTT_ENABLE=0
|
$ cc app0.c mongoose.c # Use defaults!
|
||||||
|
$ cc app1.c mongoose.c -D MG_ENABLE_IPV6=1 # Build with IPv6 enabled
|
||||||
|
$ cc app2.c mongoose.c -D MG_ARCH=MG_ARCH_FREERTOS_LWIP # Set architecture
|
||||||
|
$ cc app3.c mongoose.c -D MG_ENABLE_FS=0 -D MG_ENABLE_LOG=0 # Multiple options
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The list of supported
|
||||||
|
architectures is defined in the
|
||||||
|
[arch.h](https://github.com/cesanta/mongoose/blob/master/src/arch.h) header
|
||||||
|
file. Normally, there is no need to explicitly specify the architecture. The
|
||||||
|
architecture is guessed during the build, so setting it is not usually required.
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ---- | ----------- |
|
||||||
|
|MG_ARCH_UNIX | All UNIX-like systems like Linux, MacOS, FreeBSD, etc |
|
||||||
|
|MG_ARCH_WIN32 | Windows systems |
|
||||||
|
|MG_ARCH_ESP32 | Espressif's ESP32 |
|
||||||
|
|MG_ARCH_ESP8266 | Espressif's ESP8266 |
|
||||||
|
|MG_ARCH_FREERTOS_LWIP | All systems with FreeRTOS kernel and LwIP IP stack |
|
||||||
|
|MG_ARCH_FREERTOS_TCP | All systems with FreeRTOS kernel and FreeRTOS-Plus-TCP IP stack |
|
||||||
|
|MG_ARCH_CUSTOM | A custom architecture, discussed in the next section |
|
||||||
|
|
||||||
|
|
||||||
|
The other class of build constants is defined in
|
||||||
|
[src/config.h](https://github.com/cesanta/mongoose/blob/master/src/config.h)
|
||||||
|
together with their default values. They are tunables that include/exclude
|
||||||
|
a certain functionality or change relevant parameters.
|
||||||
|
|
||||||
|
|
||||||
Here is a list of build constants and their default values:
|
Here is a list of build constants and their default values:
|
||||||
|
|
||||||
| Name | Default | Description |
|
| Name | Default | Description |
|
||||||
| ---- | ------- | ----------- |
|
| ---- | ------- | ----------- |
|
||||||
|`MG_ENABLE_LWIP` | 0 | Use LWIP low-level API instead of BSD sockets |
|
|MG_ENABLE_SOCKET | 1 | Use BSD socket low-level API |
|
||||||
|`MG_ENABLE_SOCKET` | 1 | Use BSD socket low-level API |
|
|MG_ENABLE_MBEDTLS | 0 | Enable Mbed TLS library |
|
||||||
|`MG_ENABLE_MBEDTLS` | 0 | Enable Mbed TLS library |
|
|MG_ENABLE_OPENSSL | 0 | Enable OpenSSL library |
|
||||||
|`MG_ENABLE_OPENSSL` | 0 | Enable OpenSSL library |
|
|MG_ENABLE_FS | 1 | Enable API that use filesystem, like `mg_http_send_file()` |
|
||||||
|`MG_ENABLE_FS` | 1 | Enable API that use filesystem, like `mg_http_send_file()` |
|
|MG_ENABLE_IPV6 | 0 | Enable IPv6 |
|
||||||
|`MG_ENABLE_IPV6` | 0 | Enable IPv6 |
|
|MG_ENABLE_LOG | 1 | Enable `LOG()` macro |
|
||||||
|`MG_ENABLE_LOG` | 1 | Enable `LOG()` macro |
|
|MG_ENABLE_MD5 | 0 | Use native MD5 implementation |
|
||||||
|`MG_ENABLE_MD5` | 0 | Use native MD5 implementation |
|
|MG_ENABLE_DIRECTORY_LISTING | 0 | Enable directory listing for HTTP server |
|
||||||
|`MG_ENABLE_DIRECTORY_LISTING` | 0 | Enable directory listing for HTTP server |
|
|MG_ENABLE_SOCKETPAIR | 0 | Enable `mg_socketpair()` for multi-threading |
|
||||||
|`MG_ENABLE_SOCKETPAIR` | 0 | Enable `mg_socketpair()` for multi-threading |
|
|MG_ENABLE_SSI | 0 | Enable serving SSI files by `mg_http_serve_dir()` |
|
||||||
|`MG_ENABLE_SSI` | 0 | Enable serving SSI files by `mg_http_serve_dir()` |
|
|MG_IO_SIZE | 512 | Granularity of the send/recv IO buffer growth |
|
||||||
|`MG_IO_SIZE` | 512 | Granularity of the send/recv IO buffer growth |
|
|MG_MAX_RECV_BUF_SIZE | (3 * 1024 * 1024) | Maximum recv buffer size |
|
||||||
|`MG_MAX_RECV_BUF_SIZE` | (3 * 1024 * 1024) | Maximum recv buffer size |
|
|MG_MAX_HTTP_HEADERS | 40 | Maximum number of HTTP headers |
|
||||||
|`MG_MAX_HTTP_HEADERS` | 40 | Maximum number of HTTP headers |
|
|
||||||
|
|
||||||
NOTE: `MG_IO_SIZE` controls the maximum UDP message size, see
|
NOTE: `MG_IO_SIZE` controls the maximum UDP message size, see
|
||||||
https://github.com/cesanta/mongoose/issues/907 for details. If application
|
https://github.com/cesanta/mongoose/issues/907 for details. If application
|
||||||
@@ -235,25 +255,27 @@ uses large UDP messages, increase the `MG_IO_SIZE` limit accordingly.
|
|||||||
|
|
||||||
## Custom build
|
## Custom build
|
||||||
|
|
||||||
It is possible to use Mongoose on an architecture that is not yet supported
|
A custom build should be used for cases which is not covered by the
|
||||||
by the current codebase. In order to do so, follow these steps:
|
existing architecture options. For example, an embedded architecture that
|
||||||
|
uses some proprietary RTOS and network stack. In order to build on such
|
||||||
|
systems, follow the guideline outlined below:
|
||||||
|
|
||||||
1. Create a file called `mongoose_custom.h`, with defines and includes that
|
1. Add `-DMG_ARCH=MG_ARCH_CUSTOM` to your build flags.
|
||||||
|
|
||||||
|
2. Create a file called `mongoose_custom.h`, with defines and includes that
|
||||||
are relevant to your platform. Mongoose uses `bool` type, `MG_DIRSEP` define,
|
are relevant to your platform. Mongoose uses `bool` type, `MG_DIRSEP` define,
|
||||||
and optionally other structures like `DIR *` depending on the functionality
|
and optionally other structures like `DIR *` depending on the functionality
|
||||||
you have enabled - see previous section. Below is an example:
|
you have enabled - see previous section. Below is an example:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include <dirent.h> // For DIR *
|
|
||||||
#include <stdbool.h> // For bool
|
#include <stdbool.h> // For bool
|
||||||
#include <sys/time.h> // For gettimeofday()
|
#include <stdarg.h>
|
||||||
#include <unistd.h> // For usleep()
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
|
#define MG_INT64_FMT "%lld"
|
||||||
#define MG_ENABLE_SOCKET 0 // Disable BSD socket API, implement your own
|
#define MG_ENABLE_SOCKET 0 // Disable BSD socket API, implement your own
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Add `-DMG_ARCH=MG_ARCH_CUSTOM` to your build flags.
|
|
||||||
|
|
||||||
3. This step is optional. If you have disabled BSD socket API, your build is
|
3. This step is optional. If you have disabled BSD socket API, your build is
|
||||||
going to fail due to several undefined symbols. Create `mongoose_custom.c`
|
going to fail due to several undefined symbols. Create `mongoose_custom.c`
|
||||||
and implement the following functions (take a look at `src/sock.c` for the
|
and implement the following functions (take a look at `src/sock.c` for the
|
||||||
@@ -320,7 +342,7 @@ This example is a simple TCP echo server that listens on port 1234:
|
|||||||
static const char *s_listening_address = "tcp://0.0.0.0:1234";
|
static const char *s_listening_address = "tcp://0.0.0.0:1234";
|
||||||
|
|
||||||
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
if (ev == MG_EV_RECV) {
|
if (ev == MG_EV_READ) {
|
||||||
mg_send(c, c->recv.buf, c->recv.len); // Echo received data back
|
mg_send(c, c->recv.buf, c->recv.len); // Echo received data back
|
||||||
mg_iobuf_delete(&c->recv, c->recv.len); // And discard it
|
mg_iobuf_delete(&c->recv, c->recv.len); // And discard it
|
||||||
}
|
}
|
||||||
@@ -361,20 +383,21 @@ with some housekeeping information.
|
|||||||
struct mg_connection {
|
struct mg_connection {
|
||||||
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
||||||
struct mg_mgr *mgr; // Our container
|
struct mg_mgr *mgr; // Our container
|
||||||
struct mg_addr peer; // Remote peer address
|
struct mg_addr peer; // Remote address. For listeners, local address
|
||||||
void *fd; // Connected socket, or LWIP data
|
void *fd; // Connected socket, or LWIP data
|
||||||
|
unsigned long id; // Auto-incrementing unique connection ID
|
||||||
struct mg_iobuf recv; // Incoming data
|
struct mg_iobuf recv; // Incoming data
|
||||||
struct mg_iobuf send; // Outgoing data
|
struct mg_iobuf send; // Outgoing data
|
||||||
mg_event_handler_t fn; // User-specified event handler function
|
mg_event_handler_t fn; // User-specified event handler function
|
||||||
void *fn_data; // User-speficied function parameter
|
void *fn_data; // User-specified function parameter
|
||||||
mg_event_handler_t pfn; // Protocol-specific handler function
|
mg_event_handler_t pfn; // Protocol-specific handler function
|
||||||
void *pfn_data; // Protocol-specific function parameter
|
void *pfn_data; // Protocol-specific function parameter
|
||||||
char label[32]; // Arbitrary label
|
char label[50]; // Arbitrary label
|
||||||
void *tls; // TLS specific data
|
void *tls; // TLS specific data
|
||||||
unsigned is_listening : 1; // Listening connection
|
unsigned is_listening : 1; // Listening connection
|
||||||
unsigned is_client : 1; // Outbound (client) connection
|
unsigned is_client : 1; // Outbound (client) connection
|
||||||
unsigned is_accepted : 1; // Accepted (server) connection
|
unsigned is_accepted : 1; // Accepted (server) connection
|
||||||
unsigned is_resolving : 1; // Non-blocking DNS resolv is in progress
|
unsigned is_resolving : 1; // Non-blocking DNS resolve is in progress
|
||||||
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
||||||
unsigned is_tls : 1; // TLS-enabled connection
|
unsigned is_tls : 1; // TLS-enabled connection
|
||||||
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
||||||
@@ -389,7 +412,7 @@ struct mg_connection {
|
|||||||
```
|
```
|
||||||
|
|
||||||
A connection - either a listening connection, or an accepted connection,
|
A connection - either a listening connection, or an accepted connection,
|
||||||
or an outbout connection.
|
or an outbound connection.
|
||||||
|
|
||||||
### mg\_mgr_init()
|
### mg\_mgr_init()
|
||||||
|
|
||||||
@@ -397,7 +420,7 @@ or an outbout connection.
|
|||||||
void mg_mgr_init(struct mg_mgr *);
|
void mg_mgr_init(struct mg_mgr *);
|
||||||
```
|
```
|
||||||
|
|
||||||
Initialise event manager structure: set a list of active connections to NULL,
|
Initialize event manager structure: set a list of active connections to NULL,
|
||||||
set DNS server and timeout to their default values, etc.
|
set DNS server and timeout to their default values, etc.
|
||||||
|
|
||||||
|
|
||||||
@@ -408,7 +431,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms);
|
|||||||
```
|
```
|
||||||
|
|
||||||
Perform a single poll iteration. For each connection in the `mgr->conns` list,
|
Perform a single poll iteration. For each connection in the `mgr->conns` list,
|
||||||
- See if there is incoming data. If it is, read it into the `c->recv` buffer, send `MG_EV_RECV` event
|
- See if there is incoming data. If it is, read it into the `c->recv` buffer, send `MG_EV_READ` event
|
||||||
- See if there is data in the `c->send` buffer, and write it, send `MG_EV_WRITE` event
|
- See if there is data in the `c->send` buffer, and write it, send `MG_EV_WRITE` event
|
||||||
- If a connection is listening, accept an incoming connection if any, and send `MG_EV_ACCEPT` event to it
|
- If a connection is listening, accept an incoming connection if any, and send `MG_EV_ACCEPT` event to it
|
||||||
- Send `MG_EV_POLL` event
|
- Send `MG_EV_POLL` event
|
||||||
@@ -454,7 +477,7 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
|||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
```
|
```
|
||||||
|
|
||||||
Create an outbout connection, append this connection to `mgr->conns`.
|
Create an outbound connection, append this connection to `mgr->conns`.
|
||||||
- `url` - specifies remote IP address/port to connect to, e.g. `http://a.com`
|
- `url` - specifies remote IP address/port to connect to, e.g. `http://a.com`
|
||||||
- `fn` - an event handler function
|
- `fn` - an event handler function
|
||||||
- `fn_data` - an arbitrary pointer, which will be passed as `fn_data` when an
|
- `fn_data` - an arbitrary pointer, which will be passed as `fn_data` when an
|
||||||
@@ -530,7 +553,7 @@ by `buf`, and `len` specifies number of bytes currently stored.
|
|||||||
int mg_iobuf_init(struct mg_iobuf *io, size_t size);
|
int mg_iobuf_init(struct mg_iobuf *io, size_t size);
|
||||||
```
|
```
|
||||||
|
|
||||||
Initialise IO buffer, allocate `size` bytes. Return 1 on success,
|
Initialize IO buffer, allocate `size` bytes. Return 1 on success,
|
||||||
0 on allocation failure.
|
0 on allocation failure.
|
||||||
|
|
||||||
|
|
||||||
@@ -686,8 +709,9 @@ Write a chunk of data in chunked encoding format.
|
|||||||
|
|
||||||
```c
|
```c
|
||||||
struct mg_http_serve_opts {
|
struct mg_http_serve_opts {
|
||||||
const char *root_dir; // Web root directory, must be non-NULL
|
const char *root_dir; // Web root directory, must be non-NULL
|
||||||
const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml
|
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
|
||||||
|
const char *extra_headers; // Extra HTTP headers to add in responses
|
||||||
};
|
};
|
||||||
void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
|
void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
|
||||||
const struct mg_http_serve_opts *opts);
|
const struct mg_http_serve_opts *opts);
|
||||||
@@ -730,7 +754,7 @@ parameter.
|
|||||||
- `fmt` - a format string for the HTTP body, in a printf semantics
|
- `fmt` - a format string for the HTTP body, in a printf semantics
|
||||||
|
|
||||||
|
|
||||||
### mg\_http\_header()
|
### mg\_http\_get\_header()
|
||||||
|
|
||||||
```c
|
```c
|
||||||
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
||||||
@@ -828,6 +852,25 @@ void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
|||||||
|
|
||||||
Write a Basic `Authorization` header to the output buffer.
|
Write a Basic `Authorization` header to the output buffer.
|
||||||
|
|
||||||
|
### mg\_http\_next_\multipart()
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Parameter for mg_http_next_multipart
|
||||||
|
struct mg_http_part {
|
||||||
|
struct mg_str name; // Form field name
|
||||||
|
struct mg_str filename; // Filename for file uploads
|
||||||
|
struct mg_str body; // Part contents
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t mg_http_next_multipart(struct mg_str body, size_t offset, struct mg_http_part *part);
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse the multipart chunk in the `body` at a given `offset`. An initial
|
||||||
|
`offset` should be 0. Fill up parameters in the provided `part`, which could be
|
||||||
|
NULL. Return offset to the next chunk, or 0 if there are no more chunks.
|
||||||
|
|
||||||
|
See `form-upload` example for a usage example.
|
||||||
|
|
||||||
|
|
||||||
## Websocket
|
## Websocket
|
||||||
|
|
||||||
@@ -934,40 +977,38 @@ Create client MQTT connection.
|
|||||||
|
|
||||||
```c
|
```c
|
||||||
void mg_mqtt_pub(struct mg_connection *, struct mg_str *topic,
|
void mg_mqtt_pub(struct mg_connection *, struct mg_str *topic,
|
||||||
struct mg_str *data);
|
struct mg_str *data, int qos, bool retain);
|
||||||
```
|
```
|
||||||
|
|
||||||
Publish message `data` to the topic `topic`.
|
Publish message `data` to the topic `topic` with given QoS and retain flag.
|
||||||
|
|
||||||
|
|
||||||
### mg\_mqtt\_sub()
|
### mg\_mqtt\_sub()
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic);
|
void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic, int qos);
|
||||||
```
|
```
|
||||||
|
|
||||||
Subscribe to topic `topic`.
|
Subscribe to topic `topic` with given QoS.
|
||||||
|
|
||||||
### mg\_mqtt\_next\_sub()
|
### mg\_mqtt\_next\_sub()
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, uint8_t *qos, size_t pos);
|
||||||
uint8_t *qos, int pos);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Traverse list of subscribed topics.
|
Traverse list of subscribed topics.
|
||||||
Used to implement MQTT server when `MQTT_CMD_SUBSCRIBE` is received.
|
Used to implement MQTT server when `MQTT_CMD_SUBSCRIBE` is received.
|
||||||
Return next position. Initial position `pos` should be 4. Example:
|
Return next position, or 0 when done. Initial position `pos` should be 4. Example:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
if (ev == MG_EV_MQTT_CMD) {
|
if (ev == MG_EV_MQTT_CMD) {
|
||||||
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
||||||
if (mm->cmd == MQTT_CMD_SUBSCRIBE) {
|
if (mm->cmd == MQTT_CMD_SUBSCRIBE) {
|
||||||
int pos = 4;
|
size_t pos = 4;
|
||||||
uint8_t qos;
|
uint8_t qos;
|
||||||
struct mg_str topic;
|
struct mg_str topic;
|
||||||
while ((pos = mg_mqtt_next_sub(mm, &topic, &qos, pos)) > 0) {
|
while ((pos = mg_mqtt_next_sub(mm, &topic, &qos, pos)) > 0) {
|
||||||
LOG(LL_INFO, ("SUB [%.*s]", c->id, (int) topic.len, topic.ptr));
|
LOG(LL_INFO, ("SUB [%.*s]", (int) topic.len, topic.ptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -976,8 +1017,7 @@ if (ev == MG_EV_MQTT_CMD) {
|
|||||||
### mg\_mqtt\_next\_unsub()
|
### mg\_mqtt\_next\_unsub()
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t pos);
|
||||||
int pos);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Same as `mg_mqtt_next_sub()`, but for unsubscribed topics. The difference
|
Same as `mg_mqtt_next_sub()`, but for unsubscribed topics. The difference
|
||||||
@@ -1001,6 +1041,11 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts);
|
|||||||
|
|
||||||
Initialise TLS on a given connection.
|
Initialise TLS on a given connection.
|
||||||
|
|
||||||
|
IMPORTANT: mbedTLS implementation uses `mg_random` as RNG. The `mg_random`
|
||||||
|
is defined as weak, therefore it is possible to override Mongoose's `mg_random`
|
||||||
|
with a custom implementation. Just create your own `mg_random` function:
|
||||||
|
`void mg_random(void *buf, size_t len)`.
|
||||||
|
|
||||||
|
|
||||||
## Timers
|
## Timers
|
||||||
|
|
||||||
@@ -1014,7 +1059,7 @@ struct mg_timer {
|
|||||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||||
void (*fn)(void *); // Function to call
|
void (*fn)(void *); // Function to call
|
||||||
void *arg; // Function agrument
|
void *arg; // Function argument
|
||||||
unsigned long expire; // Expiration timestamp in milliseconds
|
unsigned long expire; // Expiration timestamp in milliseconds
|
||||||
struct mg_timer *next; // Linkage in g_timers list
|
struct mg_timer *next; // Linkage in g_timers list
|
||||||
};
|
};
|
||||||
@@ -1034,7 +1079,7 @@ Setup a timer.
|
|||||||
- `fn` - function to invoke
|
- `fn` - function to invoke
|
||||||
- `fn_data` - function argument
|
- `fn_data` - function argument
|
||||||
|
|
||||||
A timer gets initialised and linked into the `g_timers` list:
|
A timer gets initialized and linked into the `g_timers` list:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
struct mg_timer *g_timers;
|
struct mg_timer *g_timers;
|
||||||
@@ -1063,11 +1108,12 @@ past the timer's expiration time.
|
|||||||
### mg\_file\_read()
|
### mg\_file\_read()
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char *mg_file_read(const char *path);
|
char *mg_file_read(const char *path, size_t *sizep);
|
||||||
```
|
```
|
||||||
|
|
||||||
Read file contents into a nul-terminated malloc-ed string. It is a caller's
|
Read file contents into a nul-terminated malloc-ed string. It is a caller's
|
||||||
responsibility to free() a returned pointer.
|
responsibility to free() a returned pointer. If `sizep` is not NULL, it will
|
||||||
|
return a file size in bytes.
|
||||||
|
|
||||||
### mg\_file\_size()
|
### mg\_file\_size()
|
||||||
|
|
||||||
@@ -1120,7 +1166,7 @@ The glob pattern matching rules are as follows:
|
|||||||
- `?` matches any single character
|
- `?` matches any single character
|
||||||
- `*` matches zero or more characters except `/`
|
- `*` matches zero or more characters except `/`
|
||||||
- `#` matches zero or more characters
|
- `#` matches zero or more characters
|
||||||
- any other caracter matches itself
|
- any other character matches itself
|
||||||
|
|
||||||
|
|
||||||
### mg\_next\_comma\_entry()
|
### mg\_next\_comma\_entry()
|
||||||
@@ -1178,7 +1224,7 @@ char *mg_hex(const void *buf, int len, char *dst);
|
|||||||
|
|
||||||
Hex-encode binary data `buf`, `len` into a buffer `dst` and nul-terminate it.
|
Hex-encode binary data `buf`, `len` into a buffer `dst` and nul-terminate it.
|
||||||
The output buffer must be at least 2 x `len` + 1 big.
|
The output buffer must be at least 2 x `len` + 1 big.
|
||||||
Return value: `dst` pointer. The encoded characters are lowecase,
|
Return value: `dst` pointer. The encoded characters are lowercase,
|
||||||
for example `mg_hex("hi", 2, buf)` outputs `6869` and 0 byte, 5 bytes overall.
|
for example `mg_hex("hi", 2, buf)` outputs `6869` and 0 byte, 5 bytes overall.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -143,8 +143,8 @@ static void broadcast_mjpeg_frame(struct mg_mgr *mgr) {
|
|||||||
size_t nfiles = sizeof(files) / sizeof(files[0]);
|
size_t nfiles = sizeof(files) / sizeof(files[0]);
|
||||||
static size_t i;
|
static size_t i;
|
||||||
const char *path = files[i++ % nfiles];
|
const char *path = files[i++ % nfiles];
|
||||||
size_t size = mg_file_size(path);
|
size_t size = 0;
|
||||||
char *data = mg_file_read(path); // Read next file
|
char *data = mg_file_read(path, &size); // Read next file
|
||||||
struct mg_connection *c;
|
struct mg_connection *c;
|
||||||
for (c = mgr->conns; c != NULL; c = c->next) {
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
if (c->label[0] != 'S') continue; // Skip non-stream connections
|
if (c->label[0] != 'S') continue; // Skip non-stream connections
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
PROG ?= example
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG)
|
||||||
|
|
||||||
|
$(PROG):
|
||||||
|
$(CC) ../../mongoose.c -I../.. $(CFLAGS) $(EXTRA) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2021 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// HTTP request handler function. It implements the following endpoints:
|
||||||
|
// /upload - prints all submitted form elements
|
||||||
|
// all other URI - serves web_root/ directory
|
||||||
|
//
|
||||||
|
// ///////////////// IMPORTANT //////////////////////////
|
||||||
|
//
|
||||||
|
// Mongoose has a limit on input buffer, which also limits maximum upload size.
|
||||||
|
// It is controlled by the MG_MAX_RECV_BUF_SIZE constant, which is set by
|
||||||
|
// default to (3 * 1024 * 1024), i.e. 3 megabytes.
|
||||||
|
// Use -DMG_MAX_RECV_BUF_SIZE=NEW_LIMIT to override it.
|
||||||
|
//
|
||||||
|
// Also, consider changing -DMG_IO_SIZE=SOME_BIG_VALUE to increase IO buffer
|
||||||
|
// increment when reading data.
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
LOG(LL_INFO, ("New request to: [%.*s], body size: %lu", (int) hm->uri.len,
|
||||||
|
hm->uri.ptr, (unsigned long) hm->body.len));
|
||||||
|
if (mg_http_match_uri(hm, "/upload")) {
|
||||||
|
struct mg_http_part part;
|
||||||
|
size_t ofs = 0;
|
||||||
|
while ((ofs = mg_http_next_multipart(hm->body, ofs, &part)) > 0) {
|
||||||
|
LOG(LL_INFO,
|
||||||
|
("Chunk name: [%.*s] filename: [%.*s] length: %lu bytes",
|
||||||
|
(int) part.name.len, part.name.ptr, (int) part.filename.len,
|
||||||
|
part.filename.ptr, (unsigned long) part.body.len));
|
||||||
|
}
|
||||||
|
mg_http_reply(c, 200, "", "Thank you!");
|
||||||
|
} else {
|
||||||
|
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
struct mg_timer t1;
|
||||||
|
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_log_set("3");
|
||||||
|
mg_http_listen(&mgr, "http://localhost:8000", cb, NULL);
|
||||||
|
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 50);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>example</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<style>
|
||||||
|
#container { margin-right: auto; margin-left: auto; max-width: 480px; }
|
||||||
|
#info { background: #e0f0f0; border-radius: .5em; padding: 2em; }
|
||||||
|
#wrapper { margin-top: 1em; }
|
||||||
|
form * { margin: 0.2em 0; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<div id="info">
|
||||||
|
Mongoose always buffers a full HTTP message before invoking
|
||||||
|
MG_EV_HTTP_MSG event. Big POST request require of lot
|
||||||
|
of RAM to buffer everything. Therefore, standard form uploads
|
||||||
|
should be used only when Mongoose runs on a system with lots of RAM.
|
||||||
|
Otherwise, please see <code>file-updload</code> example, how
|
||||||
|
a big file could be uploaded to a device with little RAM.
|
||||||
|
<br/><br/>
|
||||||
|
In this example, a standard HTML form upload is used, which uses
|
||||||
|
<code>multipart-form-data</code> encoding with
|
||||||
|
several variables and file upload. On a server side, a
|
||||||
|
<code>mg_http_next_multipart()</code> API is used to iterate over
|
||||||
|
all submitted form elements and print their payload.
|
||||||
|
</div>
|
||||||
|
<div id="wrapper">
|
||||||
|
<form action="/upload" method="post" enctype="multipart/form-data">
|
||||||
|
<input type="text" name="field1" value="type some text here" /> <br/>
|
||||||
|
<input type="file" name="file1" /> </br>
|
||||||
|
<button type="submit">submit form</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
PROG ?= example
|
PROG ?= example
|
||||||
CFLAGS ?= -DMG_ENABLE_LINES $(EXTRA)
|
CFLAGS ?= -DMG_ENABLE_LINES $(EXTRA)
|
||||||
|
ROOT ?= $(realpath $(CURDIR)/../..)
|
||||||
|
LIN = docker run -it --rm -v $(ROOT):$(ROOT) -w $(CURDIR) mdashnet/cc2
|
||||||
|
|
||||||
ifneq ($(MBEDTLS),)
|
ifneq ($(MBEDTLS),)
|
||||||
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
||||||
@@ -14,9 +16,13 @@ endif
|
|||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
$(DEBUGGER) ./$(PROG) $(ARGS)
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
|
||||||
$(PROG): main.c
|
$(PROG): main.c
|
||||||
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
||||||
|
|
||||||
|
linux: all
|
||||||
|
linux: CFLAGS += -O2 -g -fsanitize=address,undefined,shift,null,return,bounds,alignment,object-size,bool,enum -static-libasan
|
||||||
|
linux: CC = $(LIN) cc
|
||||||
|
linux: DEBUGGER = $(LIN)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
// The very first web page in history. You can replace it from command line
|
// The very first web page in history. You can replace it from command line
|
||||||
static const char *s_url = "http://info.cern.ch";
|
static const char *s_url = "http://info.cern.ch//foo";
|
||||||
|
|
||||||
// Print HTTP response and signal that we're done
|
// Print HTTP response and signal that we're done
|
||||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
PROG ?= example
|
PROG ?= example
|
||||||
|
|
||||||
ifeq "$(MBEDTLS_DIR)" ""
|
ifneq ($(MBEDTLS_DIR),)
|
||||||
else
|
|
||||||
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS_DIR)/include -I/usr/include
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS_DIR)/include -I/usr/include
|
||||||
CFLAGS += -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
CFLAGS += -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
else ifneq ($(OPENSSL_DIR),)
|
||||||
|
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL_DIR)/include
|
||||||
|
CFLAGS += -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
|
|||||||
@@ -2,24 +2,26 @@
|
|||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// HTTP server example. This server serves both static and dynamic content.
|
// HTTP server example. This server serves both static and dynamic content.
|
||||||
|
// It opens two ports: plain HTTP on port 8000 and HTTP on port 8443.
|
||||||
// It implements the following endpoints:
|
// It implements the following endpoints:
|
||||||
// /api/f1 - respond with JSON string {"result": 123}
|
// /api/f1 - respond with JSON string {"result": 123}
|
||||||
// /api/f2/:id - wildcard example, respond with JSON string {"result": "URI"}
|
// /api/f2/:id - wildcard example, respond with JSON string {"result": "URI"}
|
||||||
// any other URI serves static files from s_web_directory
|
// any other URI serves static files from s_root_dir
|
||||||
//
|
//
|
||||||
// To enable SSL/TLS (using self-signed certificates in PEM files),
|
// To enable SSL/TLS (using self-signed certificates in PEM files),
|
||||||
// 1. Change s_listen_on from http:// to https://
|
// 1. make MBEDTLS_DIR=/path/to/your/mbedtls/installation
|
||||||
// 2. make MBEDTLS_DIR=/path/to/your/mbedtls/installation
|
// 2. curl -k https://127.0.0.1:8443
|
||||||
// 3. curl -k https://127.0.0.1:8000
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
static const char *s_listen_on = "http://0.0.0.0:8000";
|
static const char *s_http_addr = "http://0.0.0.0:8000"; // HTTP port
|
||||||
static const char *s_web_directory = ".";
|
static const char *s_https_addr = "https://0.0.0.0:8443"; // HTTPS port
|
||||||
|
static const char *s_root_dir = ".";
|
||||||
|
|
||||||
|
// We use the same event handler function for HTTP and HTTPS connections
|
||||||
|
// fn_data is NULL for plain HTTP, and non-NULL for HTTPS
|
||||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
if (ev == MG_EV_ACCEPT && mg_url_is_ssl(s_listen_on)) {
|
if (ev == MG_EV_ACCEPT && fn_data != NULL) {
|
||||||
// If s_listen_on URL is https://, tell listening connection to use TLS
|
|
||||||
struct mg_tls_opts opts = {
|
struct mg_tls_opts opts = {
|
||||||
//.ca = "ca.pem", // Uncomment to enable two-way SSL
|
//.ca = "ca.pem", // Uncomment to enable two-way SSL
|
||||||
.cert = "server.pem", // Certificate PEM file
|
.cert = "server.pem", // Certificate PEM file
|
||||||
@@ -34,7 +36,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
|
mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
|
||||||
hm->uri.ptr);
|
hm->uri.ptr);
|
||||||
} else {
|
} else {
|
||||||
struct mg_http_serve_opts opts = {.root_dir = s_web_directory};
|
struct mg_http_serve_opts opts = {.root_dir = s_root_dir};
|
||||||
mg_http_serve_dir(c, ev_data, &opts);
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,8 +47,9 @@ int main(void) {
|
|||||||
struct mg_mgr mgr; // Event manager
|
struct mg_mgr mgr; // Event manager
|
||||||
mg_log_set("2"); // Set to 3 to enable debug
|
mg_log_set("2"); // Set to 3 to enable debug
|
||||||
mg_mgr_init(&mgr); // Initialise event manager
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
mg_http_listen(&mgr, s_listen_on, fn, NULL); // Create HTTP listener
|
mg_http_listen(&mgr, s_http_addr, fn, NULL); // Create HTTP listener
|
||||||
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
mg_http_listen(&mgr, s_https_addr, fn, (void *) 1); // HTTPS listener
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
mg_tls_init(c, &opts);
|
mg_tls_init(c, &opts);
|
||||||
}
|
}
|
||||||
} else if (ev == MG_EV_CLOSE) {
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
if (c2 != NULL) c2->is_closing = 1;
|
if (c->label[0] != 'B' && c2 != NULL) c2->is_closing = 1;
|
||||||
c->fn_data = NULL;
|
c->fn_data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ ROOT ?= $(realpath $(CURDIR)/../..)
|
|||||||
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
|
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
|
||||||
CFLAGS ?= -I../.. -W -Wall -DMG_ENABLE_IPV6=1 $(DEFS) $(EXTRA)
|
CFLAGS ?= -I../.. -W -Wall -DMG_ENABLE_IPV6=1 $(DEFS) $(EXTRA)
|
||||||
VCFLAGS = /nologo /W3 /O2 /I../.. $(DEFS) $(EXTRA) /link /incremental:no /machine:IX86
|
VCFLAGS = /nologo /W3 /O2 /I../.. $(DEFS) $(EXTRA) /link /incremental:no /machine:IX86
|
||||||
VC98 = docker run --rm -e Tmp=. -v $(ROOT):$(ROOT) -w $(CURDIR) docker.io/mdashnet/vc98
|
VC98 = docker run -it --rm -e Tmp=. -v $(ROOT):$(ROOT) -w $(CURDIR) mdashnet/vc98
|
||||||
|
LIN = docker run -it --rm -v $(ROOT):$(ROOT) -w $(CURDIR) mdashnet/cc2
|
||||||
|
|
||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
$(DEBUGGER) ./$(PROG) $(ARGS)
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
@@ -14,5 +15,10 @@ $(PROG): main.c Makefile
|
|||||||
mongoose.exe: main.c
|
mongoose.exe: main.c
|
||||||
$(VC98) wine cl ../../mongoose.c main.c $(VCFLAGS) ws2_32.lib /out:$@
|
$(VC98) wine cl ../../mongoose.c main.c $(VCFLAGS) ws2_32.lib /out:$@
|
||||||
|
|
||||||
|
linux: all
|
||||||
|
linux: CFLAGS += -O2 -fsanitize=address,undefined,shift,null,return,bounds,alignment,object-size,bool,enum -static-libasan
|
||||||
|
#linux: CC = $(LIN) cc
|
||||||
|
#linux: DEBUGGER = $(LIN)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mongoose mongoose_* mongoose.*
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mongoose mongoose_* mongoose.*
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2020 Cesanta Software Limited
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
static const char *s_debug_level = "2";
|
static const char *s_debug_level = "2";
|
||||||
@@ -9,9 +10,18 @@ static const char *s_listening_address = "http://localhost:8000";
|
|||||||
static const char *s_enable_hexdump = "no";
|
static const char *s_enable_hexdump = "no";
|
||||||
static const char *s_ssi_pattern = "#.shtml";
|
static const char *s_ssi_pattern = "#.shtml";
|
||||||
|
|
||||||
|
// Handle interrupts, like Ctrl-C
|
||||||
|
static int s_signo;
|
||||||
|
static void signal_handler(int signo) {
|
||||||
|
s_signo = signo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event handler for the listening connection.
|
||||||
|
// Simply serve static files from `s_root_dir`
|
||||||
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
if (ev == MG_EV_HTTP_MSG) {
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
struct mg_http_serve_opts opts = {s_root_dir, s_ssi_pattern};
|
struct mg_http_serve_opts opts = {.root_dir = s_root_dir,
|
||||||
|
.ssi_pattern = s_ssi_pattern};
|
||||||
mg_http_serve_dir(c, ev_data, &opts);
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
}
|
}
|
||||||
(void) fn_data;
|
(void) fn_data;
|
||||||
@@ -19,8 +29,8 @@ static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
|
|
||||||
static void usage(const char *prog) {
|
static void usage(const char *prog) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Mongoose v.%s, built " __DATE__ " " __TIME__
|
"Mongoose v.%s\n"
|
||||||
"\nUsage: %s OPTIONS\n"
|
"Usage: %s OPTIONS\n"
|
||||||
" -H yes|no - enable traffic hexdump, default: '%s'\n"
|
" -H yes|no - enable traffic hexdump, default: '%s'\n"
|
||||||
" -S GLOB - glob pattern for SSI files, default: '%s'\n"
|
" -S GLOB - glob pattern for SSI files, default: '%s'\n"
|
||||||
" -d DIR - directory to serve, default: '%s'\n"
|
" -d DIR - directory to serve, default: '%s'\n"
|
||||||
@@ -54,6 +64,8 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialise stuff
|
// Initialise stuff
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
signal(SIGTERM, signal_handler);
|
||||||
mg_log_set(s_debug_level);
|
mg_log_set(s_debug_level);
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
if ((c = mg_http_listen(&mgr, s_listening_address, cb, &mgr)) == NULL) {
|
if ((c = mg_http_listen(&mgr, s_listening_address, cb, &mgr)) == NULL) {
|
||||||
@@ -65,7 +77,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// Start infinite event loop
|
// Start infinite event loop
|
||||||
LOG(LL_INFO, ("Starting Mongoose v%s, serving [%s]", MG_VERSION, s_root_dir));
|
LOG(LL_INFO, ("Starting Mongoose v%s, serving [%s]", MG_VERSION, s_root_dir));
|
||||||
for (;;) mg_mgr_poll(&mgr, 1000);
|
while (s_signo == 0) mg_mgr_poll(&mgr, 1000);
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
|
LOG(LL_INFO, ("Exiting on signal %d", s_signo));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
+12
-12
@@ -29,9 +29,9 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
// MQTT connect is successful
|
// MQTT connect is successful
|
||||||
struct mg_str topic = mg_str(s_topic), data = mg_str("hello");
|
struct mg_str topic = mg_str(s_topic), data = mg_str("hello");
|
||||||
LOG(LL_INFO, ("CONNECTED to %s", s_url));
|
LOG(LL_INFO, ("CONNECTED to %s", s_url));
|
||||||
mg_mqtt_sub(c, &topic);
|
mg_mqtt_sub(c, &topic, 1);
|
||||||
LOG(LL_INFO, ("SUBSCRIBED to %.*s", (int) topic.len, topic.ptr));
|
LOG(LL_INFO, ("SUBSCRIBED to %.*s", (int) topic.len, topic.ptr));
|
||||||
mg_mqtt_pub(c, &topic, &data);
|
mg_mqtt_pub(c, &topic, &data, 1, false);
|
||||||
LOG(LL_INFO, ("PUBSLISHED %.*s -> %.*s", (int) data.len, data.ptr,
|
LOG(LL_INFO, ("PUBSLISHED %.*s -> %.*s", (int) data.len, data.ptr,
|
||||||
(int) topic.len, topic.ptr));
|
(int) topic.len, topic.ptr));
|
||||||
} else if (ev == MG_EV_MQTT_MSG) {
|
} else if (ev == MG_EV_MQTT_MSG) {
|
||||||
@@ -47,16 +47,16 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_mgr mgr; // Event manager
|
struct mg_mgr mgr; // Event manager
|
||||||
struct mg_mqtt_opts opts; // MQTT connection options
|
struct mg_mqtt_opts opts; // MQTT connection options
|
||||||
bool done = false; // Event handler flips it to true when done
|
bool done = false; // Event handler flips it to true when done
|
||||||
mg_mgr_init(&mgr); // Initialise event manager
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
memset(&opts, 0, sizeof(opts)); // Set MQTT options
|
memset(&opts, 0, sizeof(opts)); // Set MQTT options
|
||||||
opts.qos = 1; // Set QoS to 1
|
opts.qos = 1; // Set QoS to 1
|
||||||
opts.will_topic = mg_str(s_topic); // Set last will topic
|
opts.will_topic = mg_str(s_topic); // Set last will topic
|
||||||
opts.will_message = mg_str("goodbye"); // And last will message
|
opts.will_message = mg_str("goodbye"); // And last will message
|
||||||
mg_mqtt_connect(&mgr, s_url, &opts, fn, &done); // Create client connection
|
mg_mqtt_connect(&mgr, s_url, &opts, fn, &done); // Create client connection
|
||||||
while (done == false) mg_mgr_poll(&mgr, 1000); // Event loop
|
while (done == false) mg_mgr_poll(&mgr, 1000); // Event loop
|
||||||
mg_mgr_free(&mgr); // Finished, cleanup
|
mg_mgr_free(&mgr); // Finished, cleanup
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
mm->data.ptr, (int) mm->topic.len, mm->topic.ptr));
|
mm->data.ptr, (int) mm->topic.len, mm->topic.ptr));
|
||||||
for (struct sub *sub = s_subs; sub != NULL; sub = sub->next) {
|
for (struct sub *sub = s_subs; sub != NULL; sub = sub->next) {
|
||||||
if (mg_strcmp(mm->topic, sub->topic) != 0) continue;
|
if (mg_strcmp(mm->topic, sub->topic) != 0) continue;
|
||||||
mg_mqtt_pub(sub->c, &mm->topic, &mm->data);
|
mg_mqtt_pub(sub->c, &mm->topic, &mm->data, 1, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Whitespace-only changes.
@@ -0,0 +1,620 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal.c
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief HAL module driver.
|
||||||
|
* This is the common part of the HAL initialization
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
==============================================================================
|
||||||
|
##### How to use this driver #####
|
||||||
|
==============================================================================
|
||||||
|
[..]
|
||||||
|
The common HAL driver contains a set of generic and common APIs that can be
|
||||||
|
used by the PPP peripheral drivers and the user to start using the HAL.
|
||||||
|
[..]
|
||||||
|
The HAL contains two APIs' categories:
|
||||||
|
(+) Common HAL APIs
|
||||||
|
(+) Services HAL APIs
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup HAL HAL
|
||||||
|
* @brief HAL module driver.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
|
/* Private define ------------------------------------------------------------*/
|
||||||
|
/** @addtogroup HAL_Private_Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief STM32F7xx HAL Driver version number V1.2.9
|
||||||
|
*/
|
||||||
|
#define __STM32F7xx_HAL_VERSION_MAIN (0x01) /*!< [31:24] main version */
|
||||||
|
#define __STM32F7xx_HAL_VERSION_SUB1 (0x02) /*!< [23:16] sub1 version */
|
||||||
|
#define __STM32F7xx_HAL_VERSION_SUB2 (0x09) /*!< [15:8] sub2 version */
|
||||||
|
#define __STM32F7xx_HAL_VERSION_RC (0x00) /*!< [7:0] release candidate */
|
||||||
|
#define __STM32F7xx_HAL_VERSION ((__STM32F7xx_HAL_VERSION_MAIN << 24)\
|
||||||
|
|(__STM32F7xx_HAL_VERSION_SUB1 << 16)\
|
||||||
|
|(__STM32F7xx_HAL_VERSION_SUB2 << 8 )\
|
||||||
|
|(__STM32F7xx_HAL_VERSION_RC))
|
||||||
|
|
||||||
|
#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private macro -------------------------------------------------------------*/
|
||||||
|
/* Exported variables ---------------------------------------------------------*/
|
||||||
|
/** @addtogroup HAL_Exported_Variables
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
__IO uint32_t uwTick;
|
||||||
|
uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* Invalid PRIO */
|
||||||
|
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private function prototypes -----------------------------------------------*/
|
||||||
|
/* Private functions ---------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** @defgroup HAL_Exported_Functions HAL Exported Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup HAL_Exported_Functions_Group1 Initialization and de-initialization Functions
|
||||||
|
* @brief Initialization and de-initialization functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
===============================================================================
|
||||||
|
##### Initialization and Configuration functions #####
|
||||||
|
===============================================================================
|
||||||
|
[..] This section provides functions allowing to:
|
||||||
|
(+) Initializes the Flash interface the NVIC allocation and initial clock
|
||||||
|
configuration. It initializes the systick also when timeout is needed
|
||||||
|
and the backup domain when enabled.
|
||||||
|
(+) De-Initializes common part of the HAL.
|
||||||
|
(+) Configure the time base source to have 1ms time base with a dedicated
|
||||||
|
Tick interrupt priority.
|
||||||
|
(++) SysTick timer is used by default as source of time base, but user
|
||||||
|
can eventually implement his proper time base source (a general purpose
|
||||||
|
timer for example or other time source), keeping in mind that Time base
|
||||||
|
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
|
||||||
|
handled in milliseconds basis.
|
||||||
|
(++) Time base configuration function (HAL_InitTick ()) is called automatically
|
||||||
|
at the beginning of the program after reset by HAL_Init() or at any time
|
||||||
|
when clock is configured, by HAL_RCC_ClockConfig().
|
||||||
|
(++) Source of time base is configured to generate interrupts at regular
|
||||||
|
time intervals. Care must be taken if HAL_Delay() is called from a
|
||||||
|
peripheral ISR process, the Tick interrupt line must have higher priority
|
||||||
|
(numerically lower) than the peripheral interrupt. Otherwise the caller
|
||||||
|
ISR process will be blocked.
|
||||||
|
(++) functions affecting time base configurations are declared as __weak
|
||||||
|
to make override possible in case of other implementations in user file.
|
||||||
|
@endverbatim
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function is used to initialize the HAL Library; it must be the first
|
||||||
|
* instruction to be executed in the main program (before to call any other
|
||||||
|
* HAL function), it performs the following:
|
||||||
|
* Configure the Flash prefetch, and instruction cache through ART accelerator.
|
||||||
|
* Configures the SysTick to generate an interrupt each 1 millisecond,
|
||||||
|
* which is clocked by the HSI (at this stage, the clock is not yet
|
||||||
|
* configured and thus the system is running from the internal HSI at 16 MHz).
|
||||||
|
* Set NVIC Group Priority to 4.
|
||||||
|
* Calls the HAL_MspInit() callback function defined in user file
|
||||||
|
* "stm32f7xx_hal_msp.c" to do the global low level hardware initialization
|
||||||
|
*
|
||||||
|
* @note SysTick is used as time base for the HAL_Delay() function, the application
|
||||||
|
* need to ensure that the SysTick time base is always set to 1 millisecond
|
||||||
|
* to have correct HAL operation.
|
||||||
|
* @retval HAL status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef HAL_Init(void)
|
||||||
|
{
|
||||||
|
/* Configure Instruction cache through ART accelerator */
|
||||||
|
#if (ART_ACCLERATOR_ENABLE != 0)
|
||||||
|
__HAL_FLASH_ART_ENABLE();
|
||||||
|
#endif /* ART_ACCLERATOR_ENABLE */
|
||||||
|
|
||||||
|
/* Configure Flash prefetch */
|
||||||
|
#if (PREFETCH_ENABLE != 0U)
|
||||||
|
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
|
||||||
|
#endif /* PREFETCH_ENABLE */
|
||||||
|
|
||||||
|
/* Set Interrupt Group Priority */
|
||||||
|
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
|
||||||
|
|
||||||
|
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
|
||||||
|
HAL_InitTick(TICK_INT_PRIORITY);
|
||||||
|
|
||||||
|
/* Init the low level hardware */
|
||||||
|
HAL_MspInit();
|
||||||
|
|
||||||
|
/* Return function status */
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function de-Initializes common part of the HAL and stops the systick.
|
||||||
|
* This function is optional.
|
||||||
|
* @retval HAL status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef HAL_DeInit(void)
|
||||||
|
{
|
||||||
|
/* Reset of all peripherals */
|
||||||
|
__HAL_RCC_APB1_FORCE_RESET();
|
||||||
|
__HAL_RCC_APB1_RELEASE_RESET();
|
||||||
|
|
||||||
|
__HAL_RCC_APB2_FORCE_RESET();
|
||||||
|
__HAL_RCC_APB2_RELEASE_RESET();
|
||||||
|
|
||||||
|
__HAL_RCC_AHB1_FORCE_RESET();
|
||||||
|
__HAL_RCC_AHB1_RELEASE_RESET();
|
||||||
|
|
||||||
|
__HAL_RCC_AHB2_FORCE_RESET();
|
||||||
|
__HAL_RCC_AHB2_RELEASE_RESET();
|
||||||
|
|
||||||
|
__HAL_RCC_AHB3_FORCE_RESET();
|
||||||
|
__HAL_RCC_AHB3_RELEASE_RESET();
|
||||||
|
|
||||||
|
/* De-Init the low level hardware */
|
||||||
|
HAL_MspDeInit();
|
||||||
|
|
||||||
|
/* Return function status */
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the MSP.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_MspInit(void)
|
||||||
|
{
|
||||||
|
/* NOTE : This function should not be modified, when the callback is needed,
|
||||||
|
the HAL_MspInit could be implemented in the user file
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DeInitializes the MSP.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_MspDeInit(void)
|
||||||
|
{
|
||||||
|
/* NOTE : This function should not be modified, when the callback is needed,
|
||||||
|
the HAL_MspDeInit could be implemented in the user file
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function configures the source of the time base.
|
||||||
|
* The time source is configured to have 1ms time base with a dedicated
|
||||||
|
* Tick interrupt priority.
|
||||||
|
* @note This function is called automatically at the beginning of program after
|
||||||
|
* reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig().
|
||||||
|
* @note In the default implementation, SysTick timer is the source of time base.
|
||||||
|
* It is used to generate interrupts at regular time intervals.
|
||||||
|
* Care must be taken if HAL_Delay() is called from a peripheral ISR process,
|
||||||
|
* The SysTick interrupt must have higher priority (numerically lower)
|
||||||
|
* than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
|
||||||
|
* The function is declared as __weak to be overwritten in case of other
|
||||||
|
* implementation in user file.
|
||||||
|
* @param TickPriority Tick interrupt priority.
|
||||||
|
* @retval HAL status
|
||||||
|
*/
|
||||||
|
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||||
|
{
|
||||||
|
/* Configure the SysTick to have interrupt in 1ms time basis*/
|
||||||
|
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the SysTick IRQ priority */
|
||||||
|
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||||
|
{
|
||||||
|
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
|
||||||
|
uwTickPrio = TickPriority;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return function status */
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup HAL_Exported_Functions_Group2 HAL Control functions
|
||||||
|
* @brief HAL Control functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
===============================================================================
|
||||||
|
##### HAL Control functions #####
|
||||||
|
===============================================================================
|
||||||
|
[..] This section provides functions allowing to:
|
||||||
|
(+) Provide a tick value in millisecond
|
||||||
|
(+) Provide a blocking delay in millisecond
|
||||||
|
(+) Suspend the time base source interrupt
|
||||||
|
(+) Resume the time base source interrupt
|
||||||
|
(+) Get the HAL API driver version
|
||||||
|
(+) Get the device identifier
|
||||||
|
(+) Get the device revision identifier
|
||||||
|
(+) Enable/Disable Debug module during SLEEP mode
|
||||||
|
(+) Enable/Disable Debug module during STOP mode
|
||||||
|
(+) Enable/Disable Debug module during STANDBY mode
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function is called to increment a global variable "uwTick"
|
||||||
|
* used as application time base.
|
||||||
|
* @note In the default implementation, this variable is incremented each 1ms
|
||||||
|
* in SysTick ISR.
|
||||||
|
* @note This function is declared as __weak to be overwritten in case of other
|
||||||
|
* implementations in user file.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_IncTick(void)
|
||||||
|
{
|
||||||
|
uwTick += uwTickFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Provides a tick value in millisecond.
|
||||||
|
* @note This function is declared as __weak to be overwritten in case of other
|
||||||
|
* implementations in user file.
|
||||||
|
* @retval tick value
|
||||||
|
*/
|
||||||
|
__weak uint32_t HAL_GetTick(void)
|
||||||
|
{
|
||||||
|
return uwTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function returns a tick priority.
|
||||||
|
* @retval tick priority
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetTickPrio(void)
|
||||||
|
{
|
||||||
|
return uwTickPrio;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set new tick Freq.
|
||||||
|
* @retval Status
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef status = HAL_OK;
|
||||||
|
HAL_TickFreqTypeDef prevTickFreq;
|
||||||
|
|
||||||
|
assert_param(IS_TICKFREQ(Freq));
|
||||||
|
|
||||||
|
if (uwTickFreq != Freq)
|
||||||
|
{
|
||||||
|
/* Back up uwTickFreq frequency */
|
||||||
|
prevTickFreq = uwTickFreq;
|
||||||
|
|
||||||
|
/* Update uwTickFreq global variable used by HAL_InitTick() */
|
||||||
|
uwTickFreq = Freq;
|
||||||
|
|
||||||
|
/* Apply the new tick Freq */
|
||||||
|
status = HAL_InitTick(uwTickPrio);
|
||||||
|
|
||||||
|
if (status != HAL_OK)
|
||||||
|
{
|
||||||
|
/* Restore previous tick frequency */
|
||||||
|
uwTickFreq = prevTickFreq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return tick frequency.
|
||||||
|
* @retval tick period in Hz
|
||||||
|
*/
|
||||||
|
HAL_TickFreqTypeDef HAL_GetTickFreq(void)
|
||||||
|
{
|
||||||
|
return uwTickFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function provides minimum delay (in milliseconds) based
|
||||||
|
* on variable incremented.
|
||||||
|
* @note In the default implementation , SysTick timer is the source of time base.
|
||||||
|
* It is used to generate interrupts at regular time intervals where uwTick
|
||||||
|
* is incremented.
|
||||||
|
* @note This function is declared as __weak to be overwritten in case of other
|
||||||
|
* implementations in user file.
|
||||||
|
* @param Delay specifies the delay time length, in milliseconds.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_Delay(uint32_t Delay)
|
||||||
|
{
|
||||||
|
uint32_t tickstart = HAL_GetTick();
|
||||||
|
uint32_t wait = Delay;
|
||||||
|
|
||||||
|
/* Add a freq to guarantee minimum wait */
|
||||||
|
if (wait < HAL_MAX_DELAY)
|
||||||
|
{
|
||||||
|
wait += (uint32_t)(uwTickFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((HAL_GetTick() - tickstart) < wait)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Suspend Tick increment.
|
||||||
|
* @note In the default implementation , SysTick timer is the source of time base. It is
|
||||||
|
* used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
|
||||||
|
* is called, the SysTick interrupt will be disabled and so Tick increment
|
||||||
|
* is suspended.
|
||||||
|
* @note This function is declared as __weak to be overwritten in case of other
|
||||||
|
* implementations in user file.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_SuspendTick(void)
|
||||||
|
{
|
||||||
|
/* Disable SysTick Interrupt */
|
||||||
|
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resume Tick increment.
|
||||||
|
* @note In the default implementation , SysTick timer is the source of time base. It is
|
||||||
|
* used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
|
||||||
|
* is called, the SysTick interrupt will be enabled and so Tick increment
|
||||||
|
* is resumed.
|
||||||
|
* @note This function is declared as __weak to be overwritten in case of other
|
||||||
|
* implementations in user file.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_ResumeTick(void)
|
||||||
|
{
|
||||||
|
/* Enable SysTick Interrupt */
|
||||||
|
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the HAL revision
|
||||||
|
* @retval version : 0xXYZR (8bits for each decimal, R for RC)
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetHalVersion(void)
|
||||||
|
{
|
||||||
|
return __STM32F7xx_HAL_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device revision identifier.
|
||||||
|
* @retval Device revision identifier
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetREVID(void)
|
||||||
|
{
|
||||||
|
return((DBGMCU->IDCODE) >> 16U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device identifier.
|
||||||
|
* @retval Device identifier
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetDEVID(void)
|
||||||
|
{
|
||||||
|
return((DBGMCU->IDCODE) & IDCODE_DEVID_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns first word of the unique device identifier (UID based on 96 bits)
|
||||||
|
* @retval Device identifier
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetUIDw0(void)
|
||||||
|
{
|
||||||
|
return(READ_REG(*((uint32_t *)UID_BASE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns second word of the unique device identifier (UID based on 96 bits)
|
||||||
|
* @retval Device identifier
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetUIDw1(void)
|
||||||
|
{
|
||||||
|
return(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns third word of the unique device identifier (UID based on 96 bits)
|
||||||
|
* @retval Device identifier
|
||||||
|
*/
|
||||||
|
uint32_t HAL_GetUIDw2(void)
|
||||||
|
{
|
||||||
|
return(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the Debug Module during SLEEP mode
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DBGMCU_EnableDBGSleepMode(void)
|
||||||
|
{
|
||||||
|
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable the Debug Module during SLEEP mode
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DBGMCU_DisableDBGSleepMode(void)
|
||||||
|
{
|
||||||
|
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the Debug Module during STOP mode
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DBGMCU_EnableDBGStopMode(void)
|
||||||
|
{
|
||||||
|
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable the Debug Module during STOP mode
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DBGMCU_DisableDBGStopMode(void)
|
||||||
|
{
|
||||||
|
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the Debug Module during STANDBY mode
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DBGMCU_EnableDBGStandbyMode(void)
|
||||||
|
{
|
||||||
|
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable the Debug Module during STANDBY mode
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DBGMCU_DisableDBGStandbyMode(void)
|
||||||
|
{
|
||||||
|
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables the I/O Compensation Cell.
|
||||||
|
* @note The I/O compensation cell can be used only when the device supply
|
||||||
|
* voltage ranges from 2.4 to 3.6 V.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_EnableCompensationCell(void)
|
||||||
|
{
|
||||||
|
SYSCFG->CMPCR |= SYSCFG_CMPCR_CMP_PD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Power-down the I/O Compensation Cell.
|
||||||
|
* @note The I/O compensation cell can be used only when the device supply
|
||||||
|
* voltage ranges from 2.4 to 3.6 V.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DisableCompensationCell(void)
|
||||||
|
{
|
||||||
|
SYSCFG->CMPCR &= (uint32_t)~((uint32_t)SYSCFG_CMPCR_CMP_PD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables the FMC Memory Mapping Swapping.
|
||||||
|
*
|
||||||
|
* @note SDRAM is accessible at 0x60000000
|
||||||
|
* and NOR/RAM is accessible at 0xC0000000
|
||||||
|
*
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_EnableFMCMemorySwapping(void)
|
||||||
|
{
|
||||||
|
SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disables the FMC Memory Mapping Swapping
|
||||||
|
*
|
||||||
|
* @note SDRAM is accessible at 0xC0000000 (default mapping)
|
||||||
|
* and NOR/RAM is accessible at 0x60000000 (default mapping)
|
||||||
|
*
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DisableFMCMemorySwapping(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
SYSCFG->MEMRMP &= (uint32_t)~((uint32_t)SYSCFG_MEMRMP_SWP_FMC);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (STM32F765xx) || defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx)
|
||||||
|
/**
|
||||||
|
* @brief Enable the Internal FLASH Bank Swapping.
|
||||||
|
*
|
||||||
|
* @note This function can be used only for STM32F77xx/STM32F76xx devices.
|
||||||
|
*
|
||||||
|
* @note Flash Bank2 mapped at 0x08000000 (AXI) (aliased at 0x00200000 (TCM))
|
||||||
|
* and Flash Bank1 mapped at 0x08100000 (AXI) (aliased at 0x00300000 (TCM))
|
||||||
|
*
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_EnableMemorySwappingBank(void)
|
||||||
|
{
|
||||||
|
SET_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_SWP_FB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable the Internal FLASH Bank Swapping.
|
||||||
|
*
|
||||||
|
* @note This function can be used only for STM32F77xx/STM32F76xx devices.
|
||||||
|
*
|
||||||
|
* @note The default state : Flash Bank1 mapped at 0x08000000 (AXI) (aliased at 0x00200000 (TCM))
|
||||||
|
* and Flash Bank2 mapped at 0x08100000 (AXI)( aliased at 0x00300000 (TCM))
|
||||||
|
*
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_DisableMemorySwappingBank(void)
|
||||||
|
{
|
||||||
|
CLEAR_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_SWP_FB);
|
||||||
|
}
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief This file contains all the functions prototypes for the HAL
|
||||||
|
* module driver.
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __STM32F7xx_HAL_H
|
||||||
|
#define __STM32F7xx_HAL_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal_conf.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup HAL
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** @defgroup HAL_Exported_Constants HAL Exported Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup HAL_TICK_FREQ Tick Frequency
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
HAL_TICK_FREQ_10HZ = 100U,
|
||||||
|
HAL_TICK_FREQ_100HZ = 10U,
|
||||||
|
HAL_TICK_FREQ_1KHZ = 1U,
|
||||||
|
HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ
|
||||||
|
} HAL_TickFreqTypeDef;
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup SYSCFG_BootMode Boot Mode
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define SYSCFG_MEM_BOOT_ADD0 ((uint32_t)0x00000000U)
|
||||||
|
#define SYSCFG_MEM_BOOT_ADD1 SYSCFG_MEMRMP_MEM_BOOT
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported macro ------------------------------------------------------------*/
|
||||||
|
/** @defgroup HAL_Exported_Macros HAL Exported Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @brief Freeze/Unfreeze Peripherals in Debug mode
|
||||||
|
*/
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM2() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM2_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM3() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM3_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM4() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM4_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM5() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM5_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM6() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM6_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM7() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM7_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM12() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM12_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM13() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM13_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM14() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM14_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_LPTIM1() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_LPTIM1_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_RTC() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_RTC_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_WWDG() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_WWDG_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_IWDG() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_IWDG_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_I2C1_TIMEOUT() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_I2C1_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_I2C2_TIMEOUT() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_I2C2_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_I2C3_TIMEOUT() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_I2C3_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_I2C4_TIMEOUT() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_I2C4_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_CAN1() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_CAN1_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_CAN2() (DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_CAN2_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM1() (DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM1_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM8() (DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM8_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM9() (DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM9_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM10() (DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM10_STOP))
|
||||||
|
#define __HAL_DBGMCU_FREEZE_TIM11() (DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM11_STOP))
|
||||||
|
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM2() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM2_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM3() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM3_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM4() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM4_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM5() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM5_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM6() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM6_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM7() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM7_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM12() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM12_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM13() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM13_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM14() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_TIM14_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_LPTIM1() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_LPTIM1_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_RTC() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_RTC_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_WWDG() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_WWDG_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_IWDG() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_IWDG_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_I2C1_TIMEOUT() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_I2C1_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_I2C2_TIMEOUT() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_I2C2_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_I2C3_TIMEOUT() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_I2C3_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_I2C4_TIMEOUT() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_I2C4_SMBUS_TIMEOUT))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_CAN1() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_CAN1_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_CAN2() (DBGMCU->APB1FZ &= ~(DBGMCU_APB1_FZ_DBG_CAN2_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM1() (DBGMCU->APB2FZ &= ~(DBGMCU_APB2_FZ_DBG_TIM1_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM8() (DBGMCU->APB2FZ &= ~(DBGMCU_APB2_FZ_DBG_TIM8_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM9() (DBGMCU->APB2FZ &= ~(DBGMCU_APB2_FZ_DBG_TIM9_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM10() (DBGMCU->APB2FZ &= ~(DBGMCU_APB2_FZ_DBG_TIM10_STOP))
|
||||||
|
#define __HAL_DBGMCU_UNFREEZE_TIM11() (DBGMCU->APB2FZ &= ~(DBGMCU_APB2_FZ_DBG_TIM11_STOP))
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief FMC (NOR/RAM) mapped at 0x60000000 and SDRAM mapped at 0xC0000000
|
||||||
|
*/
|
||||||
|
#define __HAL_SYSCFG_REMAPMEMORY_FMC() (SYSCFG->MEMRMP &= ~(SYSCFG_MEMRMP_SWP_FMC))
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief FMC/SDRAM mapped at 0x60000000 (NOR/RAM) mapped at 0xC0000000
|
||||||
|
*/
|
||||||
|
#define __HAL_SYSCFG_REMAPMEMORY_FMC_SDRAM() do {SYSCFG->MEMRMP &= ~(SYSCFG_MEMRMP_SWP_FMC);\
|
||||||
|
SYSCFG->MEMRMP |= (SYSCFG_MEMRMP_SWP_FMC_0);\
|
||||||
|
}while(0);
|
||||||
|
/**
|
||||||
|
* @brief Return the memory boot mapping as configured by user.
|
||||||
|
* @retval The boot mode as configured by user. The returned value can be one
|
||||||
|
* of the following values:
|
||||||
|
* @arg @ref SYSCFG_MEM_BOOT_ADD0
|
||||||
|
* @arg @ref SYSCFG_MEM_BOOT_ADD1
|
||||||
|
*/
|
||||||
|
#define __HAL_SYSCFG_GET_BOOT_MODE() READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_BOOT)
|
||||||
|
|
||||||
|
#if defined (STM32F765xx) || defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx)
|
||||||
|
/** @brief SYSCFG Break Cortex-M7 Lockup lock.
|
||||||
|
* Enable and lock the connection of Cortex-M7 LOCKUP (Hardfault) output to TIM1/8 Break input.
|
||||||
|
* @note The selected configuration is locked and can be unlocked only by system reset.
|
||||||
|
*/
|
||||||
|
#define __HAL_SYSCFG_BREAK_LOCKUP_LOCK() SET_BIT(SYSCFG->CBR, SYSCFG_CBR_CLL)
|
||||||
|
|
||||||
|
/** @brief SYSCFG Break PVD lock.
|
||||||
|
* Enable and lock the PVD connection to Timer1/8 Break input, as well as the PVDE and PLS[2:0] in the PWR_CR1 register.
|
||||||
|
* @note The selected configuration is locked and can be unlocked only by system reset.
|
||||||
|
*/
|
||||||
|
#define __HAL_SYSCFG_BREAK_PVD_LOCK() SET_BIT(SYSCFG->CBR, SYSCFG_CBR_PVDL)
|
||||||
|
#endif /* STM32F765xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup HAL_Private_Macros HAL Private Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define IS_TICKFREQ(FREQ) (((FREQ) == HAL_TICK_FREQ_10HZ) || \
|
||||||
|
((FREQ) == HAL_TICK_FREQ_100HZ) || \
|
||||||
|
((FREQ) == HAL_TICK_FREQ_1KHZ))
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Exported functions --------------------------------------------------------*/
|
||||||
|
/** @addtogroup HAL_Exported_Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** @addtogroup HAL_Exported_Functions_Group1
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Initialization and Configuration functions ******************************/
|
||||||
|
HAL_StatusTypeDef HAL_Init(void);
|
||||||
|
HAL_StatusTypeDef HAL_DeInit(void);
|
||||||
|
void HAL_MspInit(void);
|
||||||
|
void HAL_MspDeInit(void);
|
||||||
|
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported variables ---------------------------------------------------------*/
|
||||||
|
/** @addtogroup HAL_Exported_Variables
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
extern __IO uint32_t uwTick;
|
||||||
|
extern uint32_t uwTickPrio;
|
||||||
|
extern HAL_TickFreqTypeDef uwTickFreq;
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup HAL_Exported_Functions_Group2
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Peripheral Control functions ************************************************/
|
||||||
|
void HAL_IncTick(void);
|
||||||
|
void HAL_Delay(uint32_t Delay);
|
||||||
|
uint32_t HAL_GetTick(void);
|
||||||
|
uint32_t HAL_GetTickPrio(void);
|
||||||
|
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq);
|
||||||
|
HAL_TickFreqTypeDef HAL_GetTickFreq(void);
|
||||||
|
void HAL_SuspendTick(void);
|
||||||
|
void HAL_ResumeTick(void);
|
||||||
|
uint32_t HAL_GetHalVersion(void);
|
||||||
|
uint32_t HAL_GetREVID(void);
|
||||||
|
uint32_t HAL_GetDEVID(void);
|
||||||
|
uint32_t HAL_GetUIDw0(void);
|
||||||
|
uint32_t HAL_GetUIDw1(void);
|
||||||
|
uint32_t HAL_GetUIDw2(void);
|
||||||
|
void HAL_DBGMCU_EnableDBGSleepMode(void);
|
||||||
|
void HAL_DBGMCU_DisableDBGSleepMode(void);
|
||||||
|
void HAL_DBGMCU_EnableDBGStopMode(void);
|
||||||
|
void HAL_DBGMCU_DisableDBGStopMode(void);
|
||||||
|
void HAL_DBGMCU_EnableDBGStandbyMode(void);
|
||||||
|
void HAL_DBGMCU_DisableDBGStandbyMode(void);
|
||||||
|
void HAL_EnableCompensationCell(void);
|
||||||
|
void HAL_DisableCompensationCell(void);
|
||||||
|
void HAL_EnableFMCMemorySwapping(void);
|
||||||
|
void HAL_DisableFMCMemorySwapping(void);
|
||||||
|
#if defined (STM32F765xx) || defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx)
|
||||||
|
void HAL_EnableMemorySwappingBank(void);
|
||||||
|
void HAL_DisableMemorySwappingBank(void);
|
||||||
|
#endif /* STM32F765xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Private types -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
/** @defgroup HAL_Private_Variables HAL Private Variables
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Private constants ---------------------------------------------------------*/
|
||||||
|
/** @defgroup HAL_Private_Constants HAL Private Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Private macros ------------------------------------------------------------*/
|
||||||
|
/* Private functions ---------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __STM32F7xx_HAL_H */
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define HAL_ETH_MODULE_ENABLED
|
||||||
|
#define HAL_RCC_MODULE_ENABLED
|
||||||
|
#define HAL_CORTEX_MODULE_ENABLED
|
||||||
|
#define HAL_GPIO_MODULE_ENABLED
|
||||||
|
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#include "stm32f7xx_hal_cortex.h"
|
||||||
|
#include "stm32f7xx_hal_def.h"
|
||||||
|
#include "stm32f7xx_hal_rcc.h"
|
||||||
|
#include "stm32f7xx_hal_gpio.h"
|
||||||
|
|
||||||
|
#define UID_BASE 0x1FF0F420UL
|
||||||
|
#define __HAL_FLASH_ART_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_ARTEN)
|
||||||
|
#define __HAL_FLASH_PREFETCH_BUFFER_ENABLE() (FLASH->ACR |= FLASH_ACR_PRFTEN)
|
||||||
|
|
||||||
|
#define assert_param(expr) ((void) 0U)
|
||||||
|
|
||||||
|
#define HAL_MODULE_ENABLED
|
||||||
|
#define HAL_ADC_MODULE_ENABLED
|
||||||
|
#define HAL_CAN_MODULE_ENABLED
|
||||||
|
#define HAL_CEC_MODULE_ENABLED
|
||||||
|
#define HAL_CRC_MODULE_ENABLED
|
||||||
|
#define HAL_CRYP_MODULE_ENABLED
|
||||||
|
#define HAL_DAC_MODULE_ENABLED
|
||||||
|
#define HAL_DCMI_MODULE_ENABLED
|
||||||
|
#define HAL_DMA_MODULE_ENABLED
|
||||||
|
#define HAL_DMA2D_MODULE_ENABLED
|
||||||
|
#define HAL_ETH_MODULE_ENABLED
|
||||||
|
#define HAL_FLASH_MODULE_ENABLED
|
||||||
|
//#define HAL_NAND_MODULE_ENABLED
|
||||||
|
#define HAL_NOR_MODULE_ENABLED
|
||||||
|
#define HAL_SRAM_MODULE_ENABLED
|
||||||
|
#define HAL_SDRAM_MODULE_ENABLED
|
||||||
|
#define HAL_HASH_MODULE_ENABLED
|
||||||
|
#define HAL_GPIO_MODULE_ENABLED
|
||||||
|
#define HAL_I2C_MODULE_ENABLED
|
||||||
|
//#define HAL_I2S_MODULE_ENABLED
|
||||||
|
//#define HAL_IWDG_MODULE_ENABLED
|
||||||
|
#define HAL_LPTIM_MODULE_ENABLED
|
||||||
|
#define HAL_LTDC_MODULE_ENABLED
|
||||||
|
#define HAL_PWR_MODULE_ENABLED
|
||||||
|
#define HAL_QSPI_MODULE_ENABLED
|
||||||
|
#define HAL_RCC_MODULE_ENABLED
|
||||||
|
#define HAL_RNG_MODULE_ENABLED
|
||||||
|
#define HAL_RTC_MODULE_ENABLED
|
||||||
|
//#define HAL_SAI_MODULE_ENABLED
|
||||||
|
#define HAL_SD_MODULE_ENABLED
|
||||||
|
#define HAL_SPI_MODULE_ENABLED
|
||||||
|
#define HAL_TIM_MODULE_ENABLED
|
||||||
|
#define HAL_UART_MODULE_ENABLED
|
||||||
|
#define HAL_USART_MODULE_ENABLED
|
||||||
|
#define HAL_IRDA_MODULE_ENABLED
|
||||||
|
#define HAL_SMARTCARD_MODULE_ENABLED
|
||||||
|
//#define HAL_WWDG_MODULE_ENABLED
|
||||||
|
#define HAL_CORTEX_MODULE_ENABLED
|
||||||
|
//#define HAL_PCD_MODULE_ENABLED
|
||||||
|
//#define HAL_HCD_MODULE_ENABLED
|
||||||
|
|
||||||
|
/* ########################## HSE/HSI Values adaptation ##################### */
|
||||||
|
/**
|
||||||
|
* @brief Adjust the value of External High Speed oscillator (HSE) used in your
|
||||||
|
* application. This value is used by the RCC HAL module to compute the system
|
||||||
|
* frequency (when HSE is used as system clock source, directly or through the
|
||||||
|
* PLL).
|
||||||
|
*/
|
||||||
|
#if !defined(HSE_VALUE)
|
||||||
|
#define HSE_VALUE \
|
||||||
|
((uint32_t) 25000000) /*!< Value of the External oscillator in Hz */
|
||||||
|
#endif /* HSE_VALUE */
|
||||||
|
|
||||||
|
#if !defined(HSE_STARTUP_TIMEOUT)
|
||||||
|
#define HSE_STARTUP_TIMEOUT \
|
||||||
|
((uint32_t) 5000) /*!< Time out for HSE start up, in ms */
|
||||||
|
#endif /* HSE_STARTUP_TIMEOUT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal High Speed oscillator (HSI) value.
|
||||||
|
* This value is used by the RCC HAL module to compute the system
|
||||||
|
* frequency (when HSI is used as system clock source, directly or through the
|
||||||
|
* PLL).
|
||||||
|
*/
|
||||||
|
#if !defined(HSI_VALUE)
|
||||||
|
#define HSI_VALUE \
|
||||||
|
((uint32_t) 16000000) /*!< Value of the Internal oscillator in Hz*/
|
||||||
|
#endif /* HSI_VALUE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal Low Speed oscillator (LSI) value.
|
||||||
|
*/
|
||||||
|
#if !defined(LSI_VALUE)
|
||||||
|
#define LSI_VALUE ((uint32_t) 40000)
|
||||||
|
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz \
|
||||||
|
The real value may vary depending on the variations \
|
||||||
|
in voltage and temperature. */
|
||||||
|
/**
|
||||||
|
* @brief External Low Speed oscillator (LSE) value.
|
||||||
|
*/
|
||||||
|
#if !defined(LSE_VALUE)
|
||||||
|
#define LSE_VALUE \
|
||||||
|
((uint32_t) 32768) /*!< Value of the External Low Speed oscillator in Hz */
|
||||||
|
#endif /* LSE_VALUE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief External clock source for I2S peripheral
|
||||||
|
* This value is used by the I2S HAL module to compute the I2S clock
|
||||||
|
* source frequency, this source is inserted directly through I2S_CKIN pad.
|
||||||
|
*/
|
||||||
|
#if !defined(EXTERNAL_CLOCK_VALUE)
|
||||||
|
#define EXTERNAL_CLOCK_VALUE \
|
||||||
|
((uint32_t) 12288000) /*!< Value of the Internal oscillator in Hz*/
|
||||||
|
#endif /* EXTERNAL_CLOCK_VALUE */
|
||||||
|
|
||||||
|
/* Tip: To avoid modifying this file each time you need to use different HSE,
|
||||||
|
=== you can define the HSE value in your toolchain compiler preprocessor. */
|
||||||
|
|
||||||
|
/* ########################### System Configuration ######################### */
|
||||||
|
/**
|
||||||
|
* @brief This is the HAL system configuration section
|
||||||
|
*/
|
||||||
|
#define VDD_VALUE ((uint32_t) 3300) /*!< Value of VDD in mv */
|
||||||
|
#define TICK_INT_PRIORITY ((uint32_t) 0x0F) /*!< tick interrupt priority */
|
||||||
|
#define USE_RTOS 0
|
||||||
|
#define ART_ACCLERATOR_ENABLE 1 /* To enable instruction cache and prefetch */
|
||||||
|
|
||||||
|
/* ########################## Assert Selection ############################## */
|
||||||
|
/**
|
||||||
|
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||||
|
* HAL drivers code
|
||||||
|
*/
|
||||||
|
/* #define USE_FULL_ASSERT 1 */
|
||||||
|
|
||||||
|
/* ################## Ethernet peripheral configuration ##################### */
|
||||||
|
|
||||||
|
/* Section 1 : Ethernet peripheral configuration */
|
||||||
|
|
||||||
|
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
|
||||||
|
#define MAC_ADDR0 2
|
||||||
|
#define MAC_ADDR1 0
|
||||||
|
#define MAC_ADDR2 0
|
||||||
|
#define MAC_ADDR3 0
|
||||||
|
#define MAC_ADDR4 0
|
||||||
|
#define MAC_ADDR5 0
|
||||||
|
|
||||||
|
/* Definition of the Ethernet driver buffers size and count */
|
||||||
|
#define ETH_RX_BUF_SIZE \
|
||||||
|
ETH_MAX_PACKET_SIZE /* buffer size for receive */
|
||||||
|
#define ETH_TX_BUF_SIZE \
|
||||||
|
ETH_MAX_PACKET_SIZE /* buffer size for transmit */
|
||||||
|
#define ETH_RXBUFNB ((uint32_t) 8) /* 8 Rx buffers of size ETH_RX_BUF_SIZE */
|
||||||
|
#define ETH_TXBUFNB ((uint32_t) 4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
|
||||||
|
|
||||||
|
/* Section 2: PHY configuration section */
|
||||||
|
|
||||||
|
/* DP83848 PHY Address*/
|
||||||
|
#define DP83848_PHY_ADDRESS 0x01
|
||||||
|
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
|
||||||
|
#define PHY_RESET_DELAY ((uint32_t) 0x000000FF)
|
||||||
|
/* PHY Configuration delay */
|
||||||
|
#define PHY_CONFIG_DELAY ((uint32_t) 0x00000FFF)
|
||||||
|
|
||||||
|
#define PHY_READ_TO ((uint32_t) 0x0000FFFF)
|
||||||
|
#define PHY_WRITE_TO ((uint32_t) 0x0000FFFF)
|
||||||
|
|
||||||
|
/* Section 3: Common PHY Registers */
|
||||||
|
|
||||||
|
#define PHY_BCR ((uint16_t) 0x00) /*!< Transceiver Basic Control Register */
|
||||||
|
#define PHY_BSR ((uint16_t) 0x01) /*!< Transceiver Basic Status Register */
|
||||||
|
|
||||||
|
#define PHY_RESET ((uint16_t) 0x8000) /*!< PHY Reset */
|
||||||
|
#define PHY_LOOPBACK ((uint16_t) 0x4000) /*!< Select loop-back mode */
|
||||||
|
#define PHY_FULLDUPLEX_100M \
|
||||||
|
((uint16_t) 0x2100) /*!< Set the full-duplex mode at 100 Mb/s */
|
||||||
|
#define PHY_HALFDUPLEX_100M \
|
||||||
|
((uint16_t) 0x2000) /*!< Set the half-duplex mode at 100 Mb/s */
|
||||||
|
#define PHY_FULLDUPLEX_10M \
|
||||||
|
((uint16_t) 0x0100) /*!< Set the full-duplex mode at 10 Mb/s */
|
||||||
|
#define PHY_HALFDUPLEX_10M \
|
||||||
|
((uint16_t) 0x0000) /*!< Set the half-duplex mode at 10 Mb/s */
|
||||||
|
#define PHY_AUTONEGOTIATION \
|
||||||
|
((uint16_t) 0x1000) /*!< Enable auto-negotiation function */
|
||||||
|
#define PHY_RESTART_AUTONEGOTIATION \
|
||||||
|
((uint16_t) 0x0200) /*!< Restart auto-negotiation function */
|
||||||
|
#define PHY_POWERDOWN \
|
||||||
|
((uint16_t) 0x0800) /*!< Select the power down mode */
|
||||||
|
#define PHY_ISOLATE \
|
||||||
|
((uint16_t) 0x0400) /*!< Isolate PHY from MII */
|
||||||
|
|
||||||
|
#define PHY_AUTONEGO_COMPLETE \
|
||||||
|
((uint16_t) 0x0020) /*!< Auto-Negotiation process completed */
|
||||||
|
#define PHY_LINKED_STATUS \
|
||||||
|
((uint16_t) 0x0004) /*!< Valid link established */
|
||||||
|
#define PHY_JABBER_DETECTION \
|
||||||
|
((uint16_t) 0x0002) /*!< Jabber condition detected */
|
||||||
|
|
||||||
|
/* Section 4: Extended PHY Registers */
|
||||||
|
|
||||||
|
#define PHY_SR \
|
||||||
|
((uint16_t) 0x10) /*!< PHY status register Offset */
|
||||||
|
#define PHY_MICR \
|
||||||
|
((uint16_t) 0x11) /*!< MII Interrupt Control Register */
|
||||||
|
#define PHY_MISR \
|
||||||
|
((uint16_t) 0x12) /*!< MII Interrupt Status and Misc. Control Register */
|
||||||
|
|
||||||
|
#define PHY_LINK_STATUS \
|
||||||
|
((uint16_t) 0x0001) /*!< PHY Link mask */
|
||||||
|
#define PHY_SPEED_STATUS \
|
||||||
|
((uint16_t) 0x0002) /*!< PHY Speed mask */
|
||||||
|
#define PHY_DUPLEX_STATUS \
|
||||||
|
((uint16_t) 0x0004) /*!< PHY Duplex mask */
|
||||||
|
|
||||||
|
#define PHY_MICR_INT_EN \
|
||||||
|
((uint16_t) 0x0002) /*!< PHY Enable interrupts */
|
||||||
|
#define PHY_MICR_INT_OE \
|
||||||
|
((uint16_t) 0x0001) /*!< PHY Enable output interrupt events */
|
||||||
|
|
||||||
|
#define PHY_MISR_LINK_INT_EN \
|
||||||
|
((uint16_t) 0x0020) /*!< Enable Interrupt on change of link status */
|
||||||
|
#define PHY_LINK_INTERRUPT \
|
||||||
|
((uint16_t) 0x2000) /*!< PHY link status interrupt mask */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define HAL_ETH_MODULE_ENABLED
|
||||||
|
#define HAL_RCC_MODULE_ENABLED
|
||||||
|
#define HAL_CORTEX_MODULE_ENABLED
|
||||||
|
#define HAL_GPIO_MODULE_ENABLED
|
||||||
|
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#include "stm32f7xx_hal_cortex.h"
|
||||||
|
#include "stm32f7xx_hal_def.h"
|
||||||
|
#include "stm32f7xx_hal_rcc.h"
|
||||||
|
|
||||||
|
#define UID_BASE 0x1FF0F420UL
|
||||||
|
#define __HAL_FLASH_ART_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_ARTEN)
|
||||||
|
#define __HAL_FLASH_PREFETCH_BUFFER_ENABLE() (FLASH->ACR |= FLASH_ACR_PRFTEN)
|
||||||
|
|
||||||
|
#define ETH_RXBUFNB 3
|
||||||
|
#define ETH_TXBUFNB 2
|
||||||
|
#define ETH_RX_BUF_SIZE (ipconfigNETWORK_MTU + 36)
|
||||||
|
#define ETH_TX_BUF_SIZE (ipconfigNETWORK_MTU + 36)
|
||||||
|
|
||||||
|
#define assert_param(expr) ((void) 0U)
|
||||||
|
|
||||||
|
#define LAN8742A_PHY_ADDRESS 0x00
|
||||||
|
#define PHY_RESET_DELAY ((uint32_t)0x00000FFF)
|
||||||
|
#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF)
|
||||||
|
#define PHY_READ_TO ((uint32_t)0x0000FFFF)
|
||||||
|
#define PHY_WRITE_TO ((uint32_t)0x0000FFFF)
|
||||||
|
#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */
|
||||||
|
#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */
|
||||||
|
#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */
|
||||||
|
#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */
|
||||||
|
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */
|
||||||
|
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */
|
||||||
|
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */
|
||||||
|
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */
|
||||||
|
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */
|
||||||
|
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */
|
||||||
|
#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */
|
||||||
|
#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */
|
||||||
|
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
|
||||||
|
#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */
|
||||||
|
#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */
|
||||||
|
#define PHY_SR ((uint16_t)0x1F) /*!< PHY special control/ status register Offset */
|
||||||
|
#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< PHY Speed mask */
|
||||||
|
#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< PHY Duplex mask */
|
||||||
|
#define PHY_ISFR ((uint16_t)0x1D) /*!< PHY Interrupt Source Flag register Offset */
|
||||||
|
#define PHY_ISFR_INT4 ((uint16_t)0x0010) /*!< PHY Link down inturrupt */
|
||||||
|
|
||||||
|
#if !defined(HSE_VALUE)
|
||||||
|
#define HSE_VALUE \
|
||||||
|
((uint32_t) 8000000U) /*!< Value of the External oscillator in Hz */
|
||||||
|
#endif /* HSE_VALUE */
|
||||||
|
#if !defined(HSE_STARTUP_TIMEOUT)
|
||||||
|
#define HSE_STARTUP_TIMEOUT \
|
||||||
|
((uint32_t) 100U) /*!< Time out for HSE start up, in ms */
|
||||||
|
#endif /* HSE_STARTUP_TIMEOUT */
|
||||||
|
#if !defined(HSI_VALUE)
|
||||||
|
#define HSI_VALUE \
|
||||||
|
((uint32_t) 16000000U) /*!< Value of the Internal oscillator in Hz*/
|
||||||
|
#endif /* HSI_VALUE */
|
||||||
|
#if !defined(LSI_VALUE)
|
||||||
|
#define LSI_VALUE ((uint32_t) 32000U) /*!< LSI Typical Value in Hz*/
|
||||||
|
#endif
|
||||||
|
#if !defined(LSE_VALUE)
|
||||||
|
#define LSE_VALUE \
|
||||||
|
((uint32_t) 32768U) /*!< Value of the External Low Speed oscillator in Hz */
|
||||||
|
#endif /* LSE_VALUE */
|
||||||
|
#if !defined(LSE_STARTUP_TIMEOUT)
|
||||||
|
#define LSE_STARTUP_TIMEOUT \
|
||||||
|
((uint32_t) 5000U) /*!< Time out for LSE start up, in ms */
|
||||||
|
#endif /* LSE_STARTUP_TIMEOUT */
|
||||||
|
#if !defined(EXTERNAL_CLOCK_VALUE)
|
||||||
|
#define EXTERNAL_CLOCK_VALUE \
|
||||||
|
((uint32_t) 12288000U) /*!< Value of the Internal oscillator in Hz*/
|
||||||
|
#endif /* EXTERNAL_CLOCK_VALUE */
|
||||||
|
#define VDD_VALUE ((uint32_t) 3300U) /*!< Value of VDD in mv */
|
||||||
|
#define TICK_INT_PRIORITY ((uint32_t) 0x0FU) /*!< tick interrupt priority */
|
||||||
|
#define USE_RTOS 0U
|
||||||
|
#define PREFETCH_ENABLE 1U
|
||||||
|
#define ART_ACCLERATOR_ENABLE 1U /* To enable instruction cache and prefetch \
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,505 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal_cortex.c
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief CORTEX HAL module driver.
|
||||||
|
* This file provides firmware functions to manage the following
|
||||||
|
* functionalities of the CORTEX:
|
||||||
|
* + Initialization and de-initialization functions
|
||||||
|
* + Peripheral Control functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
==============================================================================
|
||||||
|
##### How to use this driver #####
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
[..]
|
||||||
|
*** How to configure Interrupts using CORTEX HAL driver ***
|
||||||
|
===========================================================
|
||||||
|
[..]
|
||||||
|
This section provides functions allowing to configure the NVIC interrupts (IRQ).
|
||||||
|
The Cortex-M4 exceptions are managed by CMSIS functions.
|
||||||
|
|
||||||
|
(#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping()
|
||||||
|
function according to the following table.
|
||||||
|
(#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority().
|
||||||
|
(#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ().
|
||||||
|
(#) please refer to programming manual for details in how to configure priority.
|
||||||
|
|
||||||
|
-@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ preemption is no more possible.
|
||||||
|
The pending IRQ priority will be managed only by the sub priority.
|
||||||
|
|
||||||
|
-@- IRQ priority order (sorted by highest to lowest priority):
|
||||||
|
(+@) Lowest preemption priority
|
||||||
|
(+@) Lowest sub priority
|
||||||
|
(+@) Lowest hardware priority (IRQ number)
|
||||||
|
|
||||||
|
[..]
|
||||||
|
*** How to configure Systick using CORTEX HAL driver ***
|
||||||
|
========================================================
|
||||||
|
[..]
|
||||||
|
Setup SysTick Timer for time base.
|
||||||
|
|
||||||
|
(+) The HAL_SYSTICK_Config() function calls the SysTick_Config() function which
|
||||||
|
is a CMSIS function that:
|
||||||
|
(++) Configures the SysTick Reload register with value passed as function parameter.
|
||||||
|
(++) Configures the SysTick IRQ priority to the lowest value (0x0F).
|
||||||
|
(++) Resets the SysTick Counter register.
|
||||||
|
(++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK).
|
||||||
|
(++) Enables the SysTick Interrupt.
|
||||||
|
(++) Starts the SysTick Counter.
|
||||||
|
|
||||||
|
(+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro
|
||||||
|
__HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
|
||||||
|
HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined
|
||||||
|
inside the stm32f7xx_hal_cortex.h file.
|
||||||
|
|
||||||
|
(+) You can change the SysTick IRQ priority by calling the
|
||||||
|
HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function
|
||||||
|
call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function.
|
||||||
|
|
||||||
|
(+) To adjust the SysTick time base, use the following formula:
|
||||||
|
|
||||||
|
Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s)
|
||||||
|
(++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function
|
||||||
|
(++) Reload Value should not exceed 0xFFFFFF
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX CORTEX
|
||||||
|
* @brief CORTEX HAL module driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||||
|
|
||||||
|
/* Private types -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
/* Private constants ---------------------------------------------------------*/
|
||||||
|
/* Private macros ------------------------------------------------------------*/
|
||||||
|
/* Private functions ---------------------------------------------------------*/
|
||||||
|
/* Exported functions --------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_Exported_Functions CORTEX Exported Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||||
|
* @brief Initialization and Configuration functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
==============================================================================
|
||||||
|
##### Initialization and de-initialization functions #####
|
||||||
|
==============================================================================
|
||||||
|
[..]
|
||||||
|
This section provides the CORTEX HAL driver functions allowing to configure Interrupts
|
||||||
|
Systick functionalities
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the priority grouping field (preemption priority and subpriority)
|
||||||
|
* using the required unlock sequence.
|
||||||
|
* @param PriorityGroup The priority grouping bits length.
|
||||||
|
* This parameter can be one of the following values:
|
||||||
|
* @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
|
||||||
|
* 4 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
|
||||||
|
* 3 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
|
||||||
|
* 2 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
|
||||||
|
* 1 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
|
||||||
|
* 0 bits for subpriority
|
||||||
|
* @note When the NVIC_PriorityGroup_0 is selected, IRQ preemption is no more possible.
|
||||||
|
* The pending IRQ priority will be managed only by the subpriority.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
|
||||||
|
|
||||||
|
/* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
|
||||||
|
NVIC_SetPriorityGrouping(PriorityGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the priority of an interrupt.
|
||||||
|
* @param IRQn External interrupt number.
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @param PreemptPriority The preemption priority for the IRQn channel.
|
||||||
|
* This parameter can be a value between 0 and 15
|
||||||
|
* A lower priority value indicates a higher priority
|
||||||
|
* @param SubPriority the subpriority level for the IRQ channel.
|
||||||
|
* This parameter can be a value between 0 and 15
|
||||||
|
* A lower priority value indicates a higher priority.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
|
||||||
|
{
|
||||||
|
uint32_t prioritygroup = 0x00;
|
||||||
|
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
|
||||||
|
assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
|
||||||
|
|
||||||
|
prioritygroup = NVIC_GetPriorityGrouping();
|
||||||
|
|
||||||
|
NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables a device specific interrupt in the NVIC interrupt controller.
|
||||||
|
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
|
||||||
|
* function should be called before.
|
||||||
|
* @param IRQn External interrupt number.
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||||
|
|
||||||
|
/* Enable interrupt */
|
||||||
|
NVIC_EnableIRQ(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disables a device specific interrupt in the NVIC interrupt controller.
|
||||||
|
* @param IRQn External interrupt number.
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||||
|
|
||||||
|
/* Disable interrupt */
|
||||||
|
NVIC_DisableIRQ(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initiates a system reset request to reset the MCU.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_SystemReset(void)
|
||||||
|
{
|
||||||
|
/* System Reset */
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||||
|
* Counter is in free running mode to generate periodic interrupts.
|
||||||
|
* @param TicksNumb Specifies the ticks Number of ticks between two interrupts.
|
||||||
|
* @retval status: - 0 Function succeeded.
|
||||||
|
* - 1 Function failed.
|
||||||
|
*/
|
||||||
|
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
|
||||||
|
{
|
||||||
|
return SysTick_Config(TicksNumb);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_Exported_Functions_Group2 Peripheral Control functions
|
||||||
|
* @brief Cortex control functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
==============================================================================
|
||||||
|
##### Peripheral Control functions #####
|
||||||
|
==============================================================================
|
||||||
|
[..]
|
||||||
|
This subsection provides a set of functions allowing to control the CORTEX
|
||||||
|
(NVIC, SYSTICK, MPU) functionalities.
|
||||||
|
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (__MPU_PRESENT == 1)
|
||||||
|
/**
|
||||||
|
* @brief Disables the MPU
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_MPU_Disable(void)
|
||||||
|
{
|
||||||
|
/* Make sure outstanding transfers are done */
|
||||||
|
__DMB();
|
||||||
|
|
||||||
|
/* Disable fault exceptions */
|
||||||
|
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
|
||||||
|
|
||||||
|
/* Disable the MPU and clear the control register*/
|
||||||
|
MPU->CTRL = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables the MPU
|
||||||
|
* @param MPU_Control Specifies the control mode of the MPU during hard fault,
|
||||||
|
* NMI, FAULTMASK and privileged access to the default memory
|
||||||
|
* This parameter can be one of the following values:
|
||||||
|
* @arg MPU_HFNMI_PRIVDEF_NONE
|
||||||
|
* @arg MPU_HARDFAULT_NMI
|
||||||
|
* @arg MPU_PRIVILEGED_DEFAULT
|
||||||
|
* @arg MPU_HFNMI_PRIVDEF
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_MPU_Enable(uint32_t MPU_Control)
|
||||||
|
{
|
||||||
|
/* Enable the MPU */
|
||||||
|
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
|
||||||
|
|
||||||
|
/* Enable fault exceptions */
|
||||||
|
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
|
||||||
|
|
||||||
|
/* Ensure MPU setting take effects */
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes and configures the Region and the memory to be protected.
|
||||||
|
* @param MPU_Init Pointer to a MPU_Region_InitTypeDef structure that contains
|
||||||
|
* the initialization and configuration information.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));
|
||||||
|
assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));
|
||||||
|
|
||||||
|
/* Set the Region number */
|
||||||
|
MPU->RNR = MPU_Init->Number;
|
||||||
|
|
||||||
|
if ((MPU_Init->Enable) != RESET)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));
|
||||||
|
assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));
|
||||||
|
assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));
|
||||||
|
assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));
|
||||||
|
assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));
|
||||||
|
assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));
|
||||||
|
assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));
|
||||||
|
assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));
|
||||||
|
|
||||||
|
MPU->RBAR = MPU_Init->BaseAddress;
|
||||||
|
MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) |
|
||||||
|
((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) |
|
||||||
|
((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) |
|
||||||
|
((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) |
|
||||||
|
((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) |
|
||||||
|
((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) |
|
||||||
|
((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) |
|
||||||
|
((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) |
|
||||||
|
((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MPU->RBAR = 0x00;
|
||||||
|
MPU->RASR = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __MPU_PRESENT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the priority grouping field from the NVIC Interrupt Controller.
|
||||||
|
* @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field)
|
||||||
|
*/
|
||||||
|
uint32_t HAL_NVIC_GetPriorityGrouping(void)
|
||||||
|
{
|
||||||
|
/* Get the PRIGROUP[10:8] field value */
|
||||||
|
return NVIC_GetPriorityGrouping();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the priority of an interrupt.
|
||||||
|
* @param IRQn External interrupt number.
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @param PriorityGroup the priority grouping bits length.
|
||||||
|
* This parameter can be one of the following values:
|
||||||
|
* @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
|
||||||
|
* 4 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
|
||||||
|
* 3 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
|
||||||
|
* 2 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
|
||||||
|
* 1 bits for subpriority
|
||||||
|
* @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
|
||||||
|
* 0 bits for subpriority
|
||||||
|
* @param pPreemptPriority Pointer on the Preemptive priority value (starting from 0).
|
||||||
|
* @param pSubPriority Pointer on the Subpriority value (starting from 0).
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
|
||||||
|
/* Get priority for Cortex-M system or device specific interrupts */
|
||||||
|
NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets Pending bit of an external interrupt.
|
||||||
|
* @param IRQn External interrupt number
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||||
|
|
||||||
|
/* Set interrupt pending */
|
||||||
|
NVIC_SetPendingIRQ(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets Pending Interrupt (reads the pending register in the NVIC
|
||||||
|
* and returns the pending bit for the specified interrupt).
|
||||||
|
* @param IRQn External interrupt number.
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @retval status: - 0 Interrupt status is not pending.
|
||||||
|
* - 1 Interrupt status is pending.
|
||||||
|
*/
|
||||||
|
uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||||
|
|
||||||
|
/* Return 1 if pending else 0 */
|
||||||
|
return NVIC_GetPendingIRQ(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the pending bit of an external interrupt.
|
||||||
|
* @param IRQn External interrupt number.
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||||
|
|
||||||
|
/* Clear pending interrupt */
|
||||||
|
NVIC_ClearPendingIRQ(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets active interrupt ( reads the active register in NVIC and returns the active bit).
|
||||||
|
* @param IRQn External interrupt number
|
||||||
|
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||||
|
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f7xxxx.h))
|
||||||
|
* @retval status: - 0 Interrupt status is not pending.
|
||||||
|
* - 1 Interrupt status is pending.
|
||||||
|
*/
|
||||||
|
uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||||
|
|
||||||
|
/* Return 1 if active else 0 */
|
||||||
|
return NVIC_GetActive(IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the SysTick clock source.
|
||||||
|
* @param CLKSource specifies the SysTick clock source.
|
||||||
|
* This parameter can be one of the following values:
|
||||||
|
* @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source.
|
||||||
|
* @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));
|
||||||
|
if (CLKSource == SYSTICK_CLKSOURCE_HCLK)
|
||||||
|
{
|
||||||
|
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles SYSTICK interrupt request.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_SYSTICK_IRQHandler(void)
|
||||||
|
{
|
||||||
|
HAL_SYSTICK_Callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SYSTICK callback.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_SYSTICK_Callback(void)
|
||||||
|
{
|
||||||
|
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||||
|
the HAL_SYSTICK_Callback could be implemented in the user file
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,406 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal_cortex.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief Header file of CORTEX HAL module.
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __STM32F7xx_HAL_CORTEX_H
|
||||||
|
#define __STM32F7xx_HAL_CORTEX_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal_def.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CORTEX
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
/** @defgroup CORTEX_Exported_Types Cortex Exported Types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (__MPU_PRESENT == 1)
|
||||||
|
/** @defgroup CORTEX_MPU_Region_Initialization_Structure_definition MPU Region Initialization Structure Definition
|
||||||
|
* @brief MPU Region initialization structure
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Enable; /*!< Specifies the status of the region.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Region_Enable */
|
||||||
|
uint8_t Number; /*!< Specifies the number of the region to protect.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Region_Number */
|
||||||
|
uint32_t BaseAddress; /*!< Specifies the base address of the region to protect. */
|
||||||
|
uint8_t Size; /*!< Specifies the size of the region to protect.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Region_Size */
|
||||||
|
uint8_t SubRegionDisable; /*!< Specifies the number of the subregion protection to disable.
|
||||||
|
This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF */
|
||||||
|
uint8_t TypeExtField; /*!< Specifies the TEX field level.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_TEX_Levels */
|
||||||
|
uint8_t AccessPermission; /*!< Specifies the region access permission type.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Region_Permission_Attributes */
|
||||||
|
uint8_t DisableExec; /*!< Specifies the instruction access status.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Instruction_Access */
|
||||||
|
uint8_t IsShareable; /*!< Specifies the shareability status of the protected region.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Access_Shareable */
|
||||||
|
uint8_t IsCacheable; /*!< Specifies the cacheable status of the region protected.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Access_Cacheable */
|
||||||
|
uint8_t IsBufferable; /*!< Specifies the bufferable status of the protected region.
|
||||||
|
This parameter can be a value of @ref CORTEX_MPU_Access_Bufferable */
|
||||||
|
}MPU_Region_InitTypeDef;
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#endif /* __MPU_PRESENT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_Exported_Constants CORTEX Exported Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_Preemption_Priority_Group CORTEX Preemption Priority Group
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007U) /*!< 0 bits for pre-emption priority
|
||||||
|
4 bits for subpriority */
|
||||||
|
#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006U) /*!< 1 bits for pre-emption priority
|
||||||
|
3 bits for subpriority */
|
||||||
|
#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005U) /*!< 2 bits for pre-emption priority
|
||||||
|
2 bits for subpriority */
|
||||||
|
#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004U) /*!< 3 bits for pre-emption priority
|
||||||
|
1 bits for subpriority */
|
||||||
|
#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003U) /*!< 4 bits for pre-emption priority
|
||||||
|
0 bits for subpriority */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_SysTick_clock_source CORTEX _SysTick clock source
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0x00000000U)
|
||||||
|
#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (__MPU_PRESENT == 1)
|
||||||
|
/** @defgroup CORTEX_MPU_HFNMI_PRIVDEF_Control MPU HFNMI and PRIVILEGED Access control
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_HFNMI_PRIVDEF_NONE ((uint32_t)0x00000000U)
|
||||||
|
#define MPU_HARDFAULT_NMI ((uint32_t)0x00000002U)
|
||||||
|
#define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004U)
|
||||||
|
#define MPU_HFNMI_PRIVDEF ((uint32_t)0x00000006U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Region_Enable CORTEX MPU Region Enable
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_REGION_ENABLE ((uint8_t)0x01U)
|
||||||
|
#define MPU_REGION_DISABLE ((uint8_t)0x00U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Instruction_Access CORTEX MPU Instruction Access
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_INSTRUCTION_ACCESS_ENABLE ((uint8_t)0x00U)
|
||||||
|
#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Access_Shareable CORTEX MPU Instruction Access Shareable
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_ACCESS_SHAREABLE ((uint8_t)0x01U)
|
||||||
|
#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Access_Cacheable CORTEX MPU Instruction Access Cacheable
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_ACCESS_CACHEABLE ((uint8_t)0x01U)
|
||||||
|
#define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Access_Bufferable CORTEX MPU Instruction Access Bufferable
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_ACCESS_BUFFERABLE ((uint8_t)0x01U)
|
||||||
|
#define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_TEX_Levels MPU TEX Levels
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_TEX_LEVEL0 ((uint8_t)0x00U)
|
||||||
|
#define MPU_TEX_LEVEL1 ((uint8_t)0x01U)
|
||||||
|
#define MPU_TEX_LEVEL2 ((uint8_t)0x02U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Region_Size CORTEX MPU Region Size
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_REGION_SIZE_32B ((uint8_t)0x04U)
|
||||||
|
#define MPU_REGION_SIZE_64B ((uint8_t)0x05U)
|
||||||
|
#define MPU_REGION_SIZE_128B ((uint8_t)0x06U)
|
||||||
|
#define MPU_REGION_SIZE_256B ((uint8_t)0x07U)
|
||||||
|
#define MPU_REGION_SIZE_512B ((uint8_t)0x08U)
|
||||||
|
#define MPU_REGION_SIZE_1KB ((uint8_t)0x09U)
|
||||||
|
#define MPU_REGION_SIZE_2KB ((uint8_t)0x0AU)
|
||||||
|
#define MPU_REGION_SIZE_4KB ((uint8_t)0x0BU)
|
||||||
|
#define MPU_REGION_SIZE_8KB ((uint8_t)0x0CU)
|
||||||
|
#define MPU_REGION_SIZE_16KB ((uint8_t)0x0DU)
|
||||||
|
#define MPU_REGION_SIZE_32KB ((uint8_t)0x0EU)
|
||||||
|
#define MPU_REGION_SIZE_64KB ((uint8_t)0x0FU)
|
||||||
|
#define MPU_REGION_SIZE_128KB ((uint8_t)0x10U)
|
||||||
|
#define MPU_REGION_SIZE_256KB ((uint8_t)0x11U)
|
||||||
|
#define MPU_REGION_SIZE_512KB ((uint8_t)0x12U)
|
||||||
|
#define MPU_REGION_SIZE_1MB ((uint8_t)0x13U)
|
||||||
|
#define MPU_REGION_SIZE_2MB ((uint8_t)0x14U)
|
||||||
|
#define MPU_REGION_SIZE_4MB ((uint8_t)0x15U)
|
||||||
|
#define MPU_REGION_SIZE_8MB ((uint8_t)0x16U)
|
||||||
|
#define MPU_REGION_SIZE_16MB ((uint8_t)0x17U)
|
||||||
|
#define MPU_REGION_SIZE_32MB ((uint8_t)0x18U)
|
||||||
|
#define MPU_REGION_SIZE_64MB ((uint8_t)0x19U)
|
||||||
|
#define MPU_REGION_SIZE_128MB ((uint8_t)0x1AU)
|
||||||
|
#define MPU_REGION_SIZE_256MB ((uint8_t)0x1BU)
|
||||||
|
#define MPU_REGION_SIZE_512MB ((uint8_t)0x1CU)
|
||||||
|
#define MPU_REGION_SIZE_1GB ((uint8_t)0x1DU)
|
||||||
|
#define MPU_REGION_SIZE_2GB ((uint8_t)0x1EU)
|
||||||
|
#define MPU_REGION_SIZE_4GB ((uint8_t)0x1FU)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Region_Permission_Attributes CORTEX MPU Region Permission Attributes
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_REGION_NO_ACCESS ((uint8_t)0x00U)
|
||||||
|
#define MPU_REGION_PRIV_RW ((uint8_t)0x01U)
|
||||||
|
#define MPU_REGION_PRIV_RW_URO ((uint8_t)0x02U)
|
||||||
|
#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03U)
|
||||||
|
#define MPU_REGION_PRIV_RO ((uint8_t)0x05U)
|
||||||
|
#define MPU_REGION_PRIV_RO_URO ((uint8_t)0x06U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CORTEX_MPU_Region_Number CORTEX MPU Region Number
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define MPU_REGION_NUMBER0 ((uint8_t)0x00U)
|
||||||
|
#define MPU_REGION_NUMBER1 ((uint8_t)0x01U)
|
||||||
|
#define MPU_REGION_NUMBER2 ((uint8_t)0x02U)
|
||||||
|
#define MPU_REGION_NUMBER3 ((uint8_t)0x03U)
|
||||||
|
#define MPU_REGION_NUMBER4 ((uint8_t)0x04U)
|
||||||
|
#define MPU_REGION_NUMBER5 ((uint8_t)0x05U)
|
||||||
|
#define MPU_REGION_NUMBER6 ((uint8_t)0x06U)
|
||||||
|
#define MPU_REGION_NUMBER7 ((uint8_t)0x07U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#endif /* __MPU_PRESENT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Exported Macros -----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Exported functions --------------------------------------------------------*/
|
||||||
|
/** @addtogroup CORTEX_Exported_Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CORTEX_Exported_Functions_Group1
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Initialization and de-initialization functions *****************************/
|
||||||
|
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
|
||||||
|
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);
|
||||||
|
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
|
||||||
|
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn);
|
||||||
|
void HAL_NVIC_SystemReset(void);
|
||||||
|
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CORTEX_Exported_Functions_Group2
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Peripheral Control functions ***********************************************/
|
||||||
|
#if (__MPU_PRESENT == 1)
|
||||||
|
void HAL_MPU_Enable(uint32_t MPU_Control);
|
||||||
|
void HAL_MPU_Disable(void);
|
||||||
|
void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init);
|
||||||
|
#endif /* __MPU_PRESENT */
|
||||||
|
uint32_t HAL_NVIC_GetPriorityGrouping(void);
|
||||||
|
void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority);
|
||||||
|
uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn);
|
||||||
|
void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn);
|
||||||
|
void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn);
|
||||||
|
uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn);
|
||||||
|
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource);
|
||||||
|
void HAL_SYSTICK_IRQHandler(void);
|
||||||
|
void HAL_SYSTICK_Callback(void);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private types -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
/* Private constants ---------------------------------------------------------*/
|
||||||
|
/* Private macros ------------------------------------------------------------*/
|
||||||
|
/** @defgroup CORTEX_Private_Macros CORTEX Private Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PRIORITYGROUP_0) || \
|
||||||
|
((GROUP) == NVIC_PRIORITYGROUP_1) || \
|
||||||
|
((GROUP) == NVIC_PRIORITYGROUP_2) || \
|
||||||
|
((GROUP) == NVIC_PRIORITYGROUP_3) || \
|
||||||
|
((GROUP) == NVIC_PRIORITYGROUP_4))
|
||||||
|
|
||||||
|
#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10U)
|
||||||
|
|
||||||
|
#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10U)
|
||||||
|
|
||||||
|
#define IS_NVIC_DEVICE_IRQ(IRQ) ((IRQ) >= 0x00)
|
||||||
|
|
||||||
|
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SYSTICK_CLKSOURCE_HCLK) || \
|
||||||
|
((SOURCE) == SYSTICK_CLKSOURCE_HCLK_DIV8))
|
||||||
|
|
||||||
|
#if (__MPU_PRESENT == 1)
|
||||||
|
#define IS_MPU_REGION_ENABLE(STATE) (((STATE) == MPU_REGION_ENABLE) || \
|
||||||
|
((STATE) == MPU_REGION_DISABLE))
|
||||||
|
|
||||||
|
#define IS_MPU_INSTRUCTION_ACCESS(STATE) (((STATE) == MPU_INSTRUCTION_ACCESS_ENABLE) || \
|
||||||
|
((STATE) == MPU_INSTRUCTION_ACCESS_DISABLE))
|
||||||
|
|
||||||
|
#define IS_MPU_ACCESS_SHAREABLE(STATE) (((STATE) == MPU_ACCESS_SHAREABLE) || \
|
||||||
|
((STATE) == MPU_ACCESS_NOT_SHAREABLE))
|
||||||
|
|
||||||
|
#define IS_MPU_ACCESS_CACHEABLE(STATE) (((STATE) == MPU_ACCESS_CACHEABLE) || \
|
||||||
|
((STATE) == MPU_ACCESS_NOT_CACHEABLE))
|
||||||
|
|
||||||
|
#define IS_MPU_ACCESS_BUFFERABLE(STATE) (((STATE) == MPU_ACCESS_BUFFERABLE) || \
|
||||||
|
((STATE) == MPU_ACCESS_NOT_BUFFERABLE))
|
||||||
|
|
||||||
|
#define IS_MPU_TEX_LEVEL(TYPE) (((TYPE) == MPU_TEX_LEVEL0) || \
|
||||||
|
((TYPE) == MPU_TEX_LEVEL1) || \
|
||||||
|
((TYPE) == MPU_TEX_LEVEL2))
|
||||||
|
|
||||||
|
#define IS_MPU_REGION_PERMISSION_ATTRIBUTE(TYPE) (((TYPE) == MPU_REGION_NO_ACCESS) || \
|
||||||
|
((TYPE) == MPU_REGION_PRIV_RW) || \
|
||||||
|
((TYPE) == MPU_REGION_PRIV_RW_URO) || \
|
||||||
|
((TYPE) == MPU_REGION_FULL_ACCESS) || \
|
||||||
|
((TYPE) == MPU_REGION_PRIV_RO) || \
|
||||||
|
((TYPE) == MPU_REGION_PRIV_RO_URO))
|
||||||
|
|
||||||
|
#define IS_MPU_REGION_NUMBER(NUMBER) (((NUMBER) == MPU_REGION_NUMBER0) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER1) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER2) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER3) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER4) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER5) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER6) || \
|
||||||
|
((NUMBER) == MPU_REGION_NUMBER7))
|
||||||
|
|
||||||
|
#define IS_MPU_REGION_SIZE(SIZE) (((SIZE) == MPU_REGION_SIZE_32B) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_64B) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_128B) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_256B) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_512B) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_1KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_2KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_4KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_8KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_16KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_32KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_64KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_128KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_256KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_512KB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_1MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_2MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_4MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_8MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_16MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_32MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_64MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_128MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_256MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_512MB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_1GB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_2GB) || \
|
||||||
|
((SIZE) == MPU_REGION_SIZE_4GB))
|
||||||
|
|
||||||
|
#define IS_MPU_SUB_REGION_DISABLE(SUBREGION) ((SUBREGION) < (uint16_t)0x00FFU)
|
||||||
|
#endif /* __MPU_PRESENT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __STM32F7xx_HAL_CORTEX_H */
|
||||||
|
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal_def.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief This file contains HAL common defines, enumeration, macros and
|
||||||
|
* structures definitions.
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __STM32F7xx_HAL_DEF
|
||||||
|
#define __STM32F7xx_HAL_DEF
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#include "Legacy/stm32_hal_legacy.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HAL Status structures definition
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
HAL_OK = 0x00U,
|
||||||
|
HAL_ERROR = 0x01U,
|
||||||
|
HAL_BUSY = 0x02U,
|
||||||
|
HAL_TIMEOUT = 0x03U
|
||||||
|
} HAL_StatusTypeDef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HAL Lock structures definition
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
HAL_UNLOCKED = 0x00U,
|
||||||
|
HAL_LOCKED = 0x01U
|
||||||
|
} HAL_LockTypeDef;
|
||||||
|
|
||||||
|
/* Exported macro ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
|
||||||
|
|
||||||
|
#define HAL_MAX_DELAY 0xFFFFFFFFU
|
||||||
|
|
||||||
|
#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) == (BIT))
|
||||||
|
#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == 0U)
|
||||||
|
|
||||||
|
#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \
|
||||||
|
do{ \
|
||||||
|
(__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
|
||||||
|
(__DMA_HANDLE__).Parent = (__HANDLE__); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/** @brief Reset the Handle's State field.
|
||||||
|
* @param __HANDLE__ specifies the Peripheral Handle.
|
||||||
|
* @note This macro can be used for the following purpose:
|
||||||
|
* - When the Handle is declared as local variable; before passing it as parameter
|
||||||
|
* to HAL_PPP_Init() for the first time, it is mandatory to use this macro
|
||||||
|
* to set to 0 the Handle's "State" field.
|
||||||
|
* Otherwise, "State" field may have any random value and the first time the function
|
||||||
|
* HAL_PPP_Init() is called, the low level hardware initialization will be missed
|
||||||
|
* (i.e. HAL_PPP_MspInit() will not be executed).
|
||||||
|
* - When there is a need to reconfigure the low level hardware: instead of calling
|
||||||
|
* HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init().
|
||||||
|
* In this later function, when the Handle's "State" field is set to 0, it will execute the function
|
||||||
|
* HAL_PPP_MspInit() which will reconfigure the low level hardware.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0U)
|
||||||
|
|
||||||
|
#if (USE_RTOS == 1U)
|
||||||
|
/* Reserved for future use */
|
||||||
|
#error "USE_RTOS should be 0 in the current HAL release"
|
||||||
|
#else
|
||||||
|
#define __HAL_LOCK(__HANDLE__) \
|
||||||
|
do{ \
|
||||||
|
if((__HANDLE__)->Lock == HAL_LOCKED) \
|
||||||
|
{ \
|
||||||
|
return HAL_BUSY; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
(__HANDLE__)->Lock = HAL_LOCKED; \
|
||||||
|
} \
|
||||||
|
}while (0U)
|
||||||
|
|
||||||
|
#define __HAL_UNLOCK(__HANDLE__) \
|
||||||
|
do{ \
|
||||||
|
(__HANDLE__)->Lock = HAL_UNLOCKED; \
|
||||||
|
}while (0U)
|
||||||
|
#endif /* USE_RTOS */
|
||||||
|
|
||||||
|
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */
|
||||||
|
#ifndef __weak
|
||||||
|
#define __weak __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#ifndef __packed
|
||||||
|
#define __packed __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
|
||||||
|
#ifndef __weak
|
||||||
|
#define __weak __attribute__((weak))
|
||||||
|
#endif /* __weak */
|
||||||
|
#ifndef __packed
|
||||||
|
#define __packed __attribute__((__packed__))
|
||||||
|
#endif /* __packed */
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
|
||||||
|
/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */
|
||||||
|
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */
|
||||||
|
#ifndef __ALIGN_BEGIN
|
||||||
|
#define __ALIGN_BEGIN
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGN_END
|
||||||
|
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||||
|
#endif
|
||||||
|
#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
|
||||||
|
#ifndef __ALIGN_END
|
||||||
|
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||||
|
#endif /* __ALIGN_END */
|
||||||
|
#ifndef __ALIGN_BEGIN
|
||||||
|
#define __ALIGN_BEGIN
|
||||||
|
#endif /* __ALIGN_BEGIN */
|
||||||
|
#else
|
||||||
|
#ifndef __ALIGN_END
|
||||||
|
#define __ALIGN_END
|
||||||
|
#endif /* __ALIGN_END */
|
||||||
|
#ifndef __ALIGN_BEGIN
|
||||||
|
#if defined (__CC_ARM) /* ARM Compiler V5*/
|
||||||
|
#define __ALIGN_BEGIN __align(4)
|
||||||
|
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||||
|
#define __ALIGN_BEGIN
|
||||||
|
#endif /* __CC_ARM */
|
||||||
|
#endif /* __ALIGN_BEGIN */
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
/* Macro to get variable aligned on 32-bytes,needed for cache maintenance purpose */
|
||||||
|
#if defined (__GNUC__) /* GNU Compiler */
|
||||||
|
#define ALIGN_32BYTES(buf) buf __attribute__ ((aligned (32)))
|
||||||
|
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||||
|
#define ALIGN_32BYTES(buf) _Pragma("data_alignment=32") buf
|
||||||
|
#elif defined (__CC_ARM) /* ARM Compiler */
|
||||||
|
#define ALIGN_32BYTES(buf) __align(32) buf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief __RAM_FUNC definition
|
||||||
|
*/
|
||||||
|
#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||||
|
/* ARM Compiler V4/V5 and V6
|
||||||
|
--------------------------
|
||||||
|
RAM functions are defined using the toolchain options.
|
||||||
|
Functions that are executed in RAM should reside in a separate source module.
|
||||||
|
Using the 'Options for File' dialog you can simply change the 'Code / Const'
|
||||||
|
area of a module to a memory space in physical RAM.
|
||||||
|
Available memory areas are declared in the 'Target' tab of the 'Options for Target'
|
||||||
|
dialog.
|
||||||
|
*/
|
||||||
|
#define __RAM_FUNC
|
||||||
|
|
||||||
|
#elif defined ( __ICCARM__ )
|
||||||
|
/* ICCARM Compiler
|
||||||
|
---------------
|
||||||
|
RAM functions are defined using a specific toolchain keyword "__ramfunc".
|
||||||
|
*/
|
||||||
|
#define __RAM_FUNC __ramfunc
|
||||||
|
|
||||||
|
#elif defined ( __GNUC__ )
|
||||||
|
/* GNU Compiler
|
||||||
|
------------
|
||||||
|
RAM functions are defined using a specific toolchain attribute
|
||||||
|
"__attribute__((section(".RamFunc")))".
|
||||||
|
*/
|
||||||
|
#define __RAM_FUNC __attribute__((section(".RamFunc")))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief __NOINLINE definition
|
||||||
|
*/
|
||||||
|
#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || defined ( __GNUC__ )
|
||||||
|
/* ARM V4/V5 and V6 & GNU Compiler
|
||||||
|
-------------------------------
|
||||||
|
*/
|
||||||
|
#define __NOINLINE __attribute__ ( (noinline) )
|
||||||
|
|
||||||
|
#elif defined ( __ICCARM__ )
|
||||||
|
/* ICCARM Compiler
|
||||||
|
---------------
|
||||||
|
*/
|
||||||
|
#define __NOINLINE _Pragma("optimize = no_inline")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ___STM32F7xx_HAL_DEF */
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,531 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal_gpio.c
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief GPIO HAL module driver.
|
||||||
|
* This file provides firmware functions to manage the following
|
||||||
|
* functionalities of the General Purpose Input/Output (GPIO) peripheral:
|
||||||
|
* + Initialization and de-initialization functions
|
||||||
|
* + IO operation functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
==============================================================================
|
||||||
|
##### GPIO Peripheral features #####
|
||||||
|
==============================================================================
|
||||||
|
[..]
|
||||||
|
Subject to the specific hardware characteristics of each I/O port listed in the datasheet, each
|
||||||
|
port bit of the General Purpose IO (GPIO) Ports, can be individually configured by software
|
||||||
|
in several modes:
|
||||||
|
(+) Input mode
|
||||||
|
(+) Analog mode
|
||||||
|
(+) Output mode
|
||||||
|
(+) Alternate function mode
|
||||||
|
(+) External interrupt/event lines
|
||||||
|
|
||||||
|
[..]
|
||||||
|
During and just after reset, the alternate functions and external interrupt
|
||||||
|
lines are not active and the I/O ports are configured in input floating mode.
|
||||||
|
|
||||||
|
[..]
|
||||||
|
All GPIO pins have weak internal pull-up and pull-down resistors, which can be
|
||||||
|
activated or not.
|
||||||
|
|
||||||
|
[..]
|
||||||
|
In Output or Alternate mode, each IO can be configured on open-drain or push-pull
|
||||||
|
type and the IO speed can be selected depending on the VDD value.
|
||||||
|
|
||||||
|
[..]
|
||||||
|
All ports have external interrupt/event capability. To use external interrupt
|
||||||
|
lines, the port must be configured in input mode. All available GPIO pins are
|
||||||
|
connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
|
||||||
|
|
||||||
|
[..]
|
||||||
|
The external interrupt/event controller consists of up to 23 edge detectors
|
||||||
|
(16 lines are connected to GPIO) for generating event/interrupt requests (each
|
||||||
|
input line can be independently configured to select the type (interrupt or event)
|
||||||
|
and the corresponding trigger event (rising or falling or both). Each line can
|
||||||
|
also be masked independently.
|
||||||
|
|
||||||
|
##### How to use this driver #####
|
||||||
|
==============================================================================
|
||||||
|
[..]
|
||||||
|
(#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
|
||||||
|
|
||||||
|
(#) Configure the GPIO pin(s) using HAL_GPIO_Init().
|
||||||
|
(++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
|
||||||
|
(++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
|
||||||
|
structure.
|
||||||
|
(++) In case of Output or alternate function mode selection: the speed is
|
||||||
|
configured through "Speed" member from GPIO_InitTypeDef structure.
|
||||||
|
(++) In alternate mode is selection, the alternate function connected to the IO
|
||||||
|
is configured through "Alternate" member from GPIO_InitTypeDef structure.
|
||||||
|
(++) Analog mode is required when a pin is to be used as ADC channel
|
||||||
|
or DAC output.
|
||||||
|
(++) In case of external interrupt/event selection the "Mode" member from
|
||||||
|
GPIO_InitTypeDef structure select the type (interrupt or event) and
|
||||||
|
the corresponding trigger event (rising or falling or both).
|
||||||
|
|
||||||
|
(#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
|
||||||
|
mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
|
||||||
|
HAL_NVIC_EnableIRQ().
|
||||||
|
|
||||||
|
(#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
|
||||||
|
|
||||||
|
(#) To set/reset the level of a pin configured in output mode use
|
||||||
|
HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
|
||||||
|
|
||||||
|
(#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
|
||||||
|
|
||||||
|
|
||||||
|
(#) During and just after reset, the alternate functions are not
|
||||||
|
active and the GPIO pins are configured in input floating mode (except JTAG
|
||||||
|
pins).
|
||||||
|
|
||||||
|
(#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
|
||||||
|
(PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
|
||||||
|
priority over the GPIO function.
|
||||||
|
|
||||||
|
(#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
|
||||||
|
general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
|
||||||
|
The HSE has priority over the GPIO function.
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO GPIO
|
||||||
|
* @brief GPIO HAL module driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||||
|
|
||||||
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
|
/* Private define ------------------------------------------------------------*/
|
||||||
|
/** @addtogroup GPIO_Private_Constants GPIO Private Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GPIO_MODE ((uint32_t)0x00000003U)
|
||||||
|
#define EXTI_MODE ((uint32_t)0x10000000U)
|
||||||
|
#define GPIO_MODE_IT ((uint32_t)0x00010000U)
|
||||||
|
#define GPIO_MODE_EVT ((uint32_t)0x00020000U)
|
||||||
|
#define RISING_EDGE ((uint32_t)0x00100000U)
|
||||||
|
#define FALLING_EDGE ((uint32_t)0x00200000U)
|
||||||
|
#define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010U)
|
||||||
|
|
||||||
|
#define GPIO_NUMBER ((uint32_t)16U)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Private macro -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
/* Private function prototypes -----------------------------------------------*/
|
||||||
|
/* Private functions ---------------------------------------------------------*/
|
||||||
|
/* Exported functions --------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIO_Exported_Functions GPIO Exported Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||||
|
* @brief Initialization and Configuration functions
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
===============================================================================
|
||||||
|
##### Initialization and de-initialization functions #####
|
||||||
|
===============================================================================
|
||||||
|
[..]
|
||||||
|
This section provides functions allowing to initialize and de-initialize the GPIOs
|
||||||
|
to be ready for use.
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
|
||||||
|
* @param GPIOx where x can be (A..K) to select the GPIO peripheral.
|
||||||
|
* @param GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
|
||||||
|
* the configuration information for the specified GPIO peripheral.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
|
||||||
|
{
|
||||||
|
uint32_t position = 0x00;
|
||||||
|
uint32_t ioposition = 0x00;
|
||||||
|
uint32_t iocurrent = 0x00;
|
||||||
|
uint32_t temp = 0x00;
|
||||||
|
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
|
||||||
|
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
|
||||||
|
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
|
||||||
|
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
|
||||||
|
|
||||||
|
/* Configure the port pins */
|
||||||
|
for(position = 0; position < GPIO_NUMBER; position++)
|
||||||
|
{
|
||||||
|
/* Get the IO position */
|
||||||
|
ioposition = ((uint32_t)0x01) << position;
|
||||||
|
/* Get the current IO position */
|
||||||
|
iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
|
||||||
|
|
||||||
|
if(iocurrent == ioposition)
|
||||||
|
{
|
||||||
|
/*--------------------- GPIO Mode Configuration ------------------------*/
|
||||||
|
/* In case of Output or Alternate function mode selection */
|
||||||
|
if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
|
||||||
|
(GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
|
||||||
|
{
|
||||||
|
/* Check the Speed parameter */
|
||||||
|
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
|
||||||
|
/* Configure the IO Speed */
|
||||||
|
temp = GPIOx->OSPEEDR;
|
||||||
|
temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));
|
||||||
|
temp |= (GPIO_Init->Speed << (position * 2));
|
||||||
|
GPIOx->OSPEEDR = temp;
|
||||||
|
|
||||||
|
/* Configure the IO Output Type */
|
||||||
|
temp = GPIOx->OTYPER;
|
||||||
|
temp &= ~(GPIO_OTYPER_OT_0 << position) ;
|
||||||
|
temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);
|
||||||
|
GPIOx->OTYPER = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Activate the Pull-up or Pull down resistor for the current IO */
|
||||||
|
temp = GPIOx->PUPDR;
|
||||||
|
temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));
|
||||||
|
temp |= ((GPIO_Init->Pull) << (position * 2));
|
||||||
|
GPIOx->PUPDR = temp;
|
||||||
|
|
||||||
|
/* In case of Alternate function mode selection */
|
||||||
|
if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
|
||||||
|
{
|
||||||
|
/* Check the Alternate function parameter */
|
||||||
|
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
|
||||||
|
|
||||||
|
/* Configure Alternate function mapped with the current IO */
|
||||||
|
temp = GPIOx->AFR[position >> 3];
|
||||||
|
temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
|
||||||
|
temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
|
||||||
|
GPIOx->AFR[position >> 3] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
|
||||||
|
temp = GPIOx->MODER;
|
||||||
|
temp &= ~(GPIO_MODER_MODER0 << (position * 2));
|
||||||
|
temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
|
||||||
|
GPIOx->MODER = temp;
|
||||||
|
|
||||||
|
/*--------------------- EXTI Mode Configuration ------------------------*/
|
||||||
|
/* Configure the External Interrupt or event for the current IO */
|
||||||
|
if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
|
||||||
|
{
|
||||||
|
/* Enable SYSCFG Clock */
|
||||||
|
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||||
|
|
||||||
|
temp = SYSCFG->EXTICR[position >> 2];
|
||||||
|
temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
|
||||||
|
temp |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03)));
|
||||||
|
SYSCFG->EXTICR[position >> 2] = temp;
|
||||||
|
|
||||||
|
/* Clear EXTI line configuration */
|
||||||
|
temp = EXTI->IMR;
|
||||||
|
temp &= ~((uint32_t)iocurrent);
|
||||||
|
if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
|
||||||
|
{
|
||||||
|
temp |= iocurrent;
|
||||||
|
}
|
||||||
|
EXTI->IMR = temp;
|
||||||
|
|
||||||
|
temp = EXTI->EMR;
|
||||||
|
temp &= ~((uint32_t)iocurrent);
|
||||||
|
if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
|
||||||
|
{
|
||||||
|
temp |= iocurrent;
|
||||||
|
}
|
||||||
|
EXTI->EMR = temp;
|
||||||
|
|
||||||
|
/* Clear Rising Falling edge configuration */
|
||||||
|
temp = EXTI->RTSR;
|
||||||
|
temp &= ~((uint32_t)iocurrent);
|
||||||
|
if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
|
||||||
|
{
|
||||||
|
temp |= iocurrent;
|
||||||
|
}
|
||||||
|
EXTI->RTSR = temp;
|
||||||
|
|
||||||
|
temp = EXTI->FTSR;
|
||||||
|
temp &= ~((uint32_t)iocurrent);
|
||||||
|
if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
|
||||||
|
{
|
||||||
|
temp |= iocurrent;
|
||||||
|
}
|
||||||
|
EXTI->FTSR = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief De-initializes the GPIOx peripheral registers to their default reset values.
|
||||||
|
* @param GPIOx where x can be (A..K) to select the GPIO peripheral.
|
||||||
|
* @param GPIO_Pin specifies the port bit to be written.
|
||||||
|
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
|
||||||
|
{
|
||||||
|
uint32_t position;
|
||||||
|
uint32_t ioposition = 0x00;
|
||||||
|
uint32_t iocurrent = 0x00;
|
||||||
|
uint32_t tmp = 0x00;
|
||||||
|
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
|
||||||
|
|
||||||
|
/* Configure the port pins */
|
||||||
|
for(position = 0; position < GPIO_NUMBER; position++)
|
||||||
|
{
|
||||||
|
/* Get the IO position */
|
||||||
|
ioposition = ((uint32_t)0x01) << position;
|
||||||
|
/* Get the current IO position */
|
||||||
|
iocurrent = (GPIO_Pin) & ioposition;
|
||||||
|
|
||||||
|
if(iocurrent == ioposition)
|
||||||
|
{
|
||||||
|
/*------------------------- EXTI Mode Configuration --------------------*/
|
||||||
|
tmp = SYSCFG->EXTICR[position >> 2];
|
||||||
|
tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
|
||||||
|
if(tmp == ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03))))
|
||||||
|
{
|
||||||
|
/* Clear EXTI line configuration */
|
||||||
|
EXTI->IMR &= ~((uint32_t)iocurrent);
|
||||||
|
EXTI->EMR &= ~((uint32_t)iocurrent);
|
||||||
|
|
||||||
|
/* Clear Rising Falling edge configuration */
|
||||||
|
EXTI->RTSR &= ~((uint32_t)iocurrent);
|
||||||
|
EXTI->FTSR &= ~((uint32_t)iocurrent);
|
||||||
|
|
||||||
|
/* Configure the External Interrupt or event for the current IO */
|
||||||
|
tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
|
||||||
|
SYSCFG->EXTICR[position >> 2] &= ~tmp;
|
||||||
|
}
|
||||||
|
/*------------------------- GPIO Mode Configuration --------------------*/
|
||||||
|
/* Configure IO Direction in Input Floating Mode */
|
||||||
|
GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (position * 2));
|
||||||
|
|
||||||
|
/* Configure the default Alternate Function in current IO */
|
||||||
|
GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
|
||||||
|
|
||||||
|
/* Deactivate the Pull-up and Pull-down resistor for the current IO */
|
||||||
|
GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));
|
||||||
|
|
||||||
|
/* Configure the default value IO Output Type */
|
||||||
|
GPIOx->OTYPER &= ~(GPIO_OTYPER_OT_0 << position) ;
|
||||||
|
|
||||||
|
/* Configure the default value for IO Speed */
|
||||||
|
GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
|
||||||
|
* @brief GPIO Read and Write
|
||||||
|
*
|
||||||
|
@verbatim
|
||||||
|
===============================================================================
|
||||||
|
##### IO operation functions #####
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
@endverbatim
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads the specified input port pin.
|
||||||
|
* @param GPIOx where x can be (A..K) to select the GPIO peripheral.
|
||||||
|
* @param GPIO_Pin specifies the port bit to read.
|
||||||
|
* This parameter can be GPIO_PIN_x where x can be (0..15).
|
||||||
|
* @retval The input port pin value.
|
||||||
|
*/
|
||||||
|
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
|
||||||
|
{
|
||||||
|
GPIO_PinState bitstatus;
|
||||||
|
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||||
|
|
||||||
|
if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
|
||||||
|
{
|
||||||
|
bitstatus = GPIO_PIN_SET;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitstatus = GPIO_PIN_RESET;
|
||||||
|
}
|
||||||
|
return bitstatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets or clears the selected data port bit.
|
||||||
|
*
|
||||||
|
* @note This function uses GPIOx_BSRR register to allow atomic read/modify
|
||||||
|
* accesses. In this way, there is no risk of an IRQ occurring between
|
||||||
|
* the read and the modify access.
|
||||||
|
*
|
||||||
|
* @param GPIOx where x can be (A..K) to select the GPIO peripheral.
|
||||||
|
* @param GPIO_Pin specifies the port bit to be written.
|
||||||
|
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
|
||||||
|
* @param PinState specifies the value to be written to the selected bit.
|
||||||
|
* This parameter can be one of the GPIO_PinState enum values:
|
||||||
|
* @arg GPIO_PIN_RESET: to clear the port pin
|
||||||
|
* @arg GPIO_PIN_SET: to set the port pin
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
|
||||||
|
{
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||||
|
assert_param(IS_GPIO_PIN_ACTION(PinState));
|
||||||
|
|
||||||
|
if(PinState != GPIO_PIN_RESET)
|
||||||
|
{
|
||||||
|
GPIOx->BSRR = GPIO_Pin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Toggles the specified GPIO pins.
|
||||||
|
* @param GPIOx Where x can be (A..I) to select the GPIO peripheral.
|
||||||
|
* @param GPIO_Pin Specifies the pins to be toggled.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
|
||||||
|
{
|
||||||
|
uint32_t odr;
|
||||||
|
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||||
|
|
||||||
|
/* get current Output Data Register value */
|
||||||
|
odr = GPIOx->ODR;
|
||||||
|
|
||||||
|
/* Set selected pins that were at low level, and reset ones that were high */
|
||||||
|
GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Locks GPIO Pins configuration registers.
|
||||||
|
* @note The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
|
||||||
|
* GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
|
||||||
|
* @note The configuration of the locked GPIO pins can no longer be modified
|
||||||
|
* until the next reset.
|
||||||
|
* @param GPIOx where x can be (A..F) to select the GPIO peripheral for STM32F7 family
|
||||||
|
* @param GPIO_Pin specifies the port bit to be locked.
|
||||||
|
* This parameter can be any combination of GPIO_PIN_x where x can be (0..15).
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
|
||||||
|
{
|
||||||
|
__IO uint32_t tmp = GPIO_LCKR_LCKK;
|
||||||
|
|
||||||
|
/* Check the parameters */
|
||||||
|
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||||
|
|
||||||
|
/* Apply lock key write sequence */
|
||||||
|
tmp |= GPIO_Pin;
|
||||||
|
/* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
|
||||||
|
GPIOx->LCKR = tmp;
|
||||||
|
/* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
|
||||||
|
GPIOx->LCKR = GPIO_Pin;
|
||||||
|
/* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
|
||||||
|
GPIOx->LCKR = tmp;
|
||||||
|
/* Read LCKR register. This read is mandatory to complete key lock sequence */
|
||||||
|
tmp = GPIOx->LCKR;
|
||||||
|
|
||||||
|
/* Read again in order to confirm lock is active */
|
||||||
|
if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)
|
||||||
|
{
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles EXTI interrupt request.
|
||||||
|
* @param GPIO_Pin Specifies the pins connected EXTI line
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
|
||||||
|
{
|
||||||
|
/* EXTI line interrupt detected */
|
||||||
|
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
|
||||||
|
{
|
||||||
|
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
|
||||||
|
HAL_GPIO_EXTI_Callback(GPIO_Pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EXTI line detection callbacks.
|
||||||
|
* @param GPIO_Pin Specifies the pins connected EXTI line
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
|
||||||
|
{
|
||||||
|
/* Prevent unused argument(s) compilation warning */
|
||||||
|
UNUSED(GPIO_Pin);
|
||||||
|
|
||||||
|
/* NOTE: This function Should not be modified, when the callback is needed,
|
||||||
|
the HAL_GPIO_EXTI_Callback could be implemented in the user file
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,309 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal_gpio.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief Header file of GPIO HAL module.
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __STM32F7xx_HAL_GPIO_H
|
||||||
|
#define __STM32F7xx_HAL_GPIO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal_def.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup GPIO
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIO_Exported_Types GPIO Exported Types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GPIO Init structure definition
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t Pin; /*!< Specifies the GPIO pins to be configured.
|
||||||
|
This parameter can be any value of @ref GPIO_pins_define */
|
||||||
|
|
||||||
|
uint32_t Mode; /*!< Specifies the operating mode for the selected pins.
|
||||||
|
This parameter can be a value of @ref GPIO_mode_define */
|
||||||
|
|
||||||
|
uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
|
||||||
|
This parameter can be a value of @ref GPIO_pull_define */
|
||||||
|
|
||||||
|
uint32_t Speed; /*!< Specifies the speed for the selected pins.
|
||||||
|
This parameter can be a value of @ref GPIO_speed_define */
|
||||||
|
|
||||||
|
uint32_t Alternate; /*!< Peripheral to be connected to the selected pins.
|
||||||
|
This parameter can be a value of @ref GPIO_Alternate_function_selection */
|
||||||
|
}GPIO_InitTypeDef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GPIO Bit SET and Bit RESET enumeration
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GPIO_PIN_RESET = 0,
|
||||||
|
GPIO_PIN_SET
|
||||||
|
}GPIO_PinState;
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_Exported_Constants GPIO Exported Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_pins_define GPIO pins define
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GPIO_PIN_0 ((uint16_t)0x0001U) /* Pin 0 selected */
|
||||||
|
#define GPIO_PIN_1 ((uint16_t)0x0002U) /* Pin 1 selected */
|
||||||
|
#define GPIO_PIN_2 ((uint16_t)0x0004U) /* Pin 2 selected */
|
||||||
|
#define GPIO_PIN_3 ((uint16_t)0x0008U) /* Pin 3 selected */
|
||||||
|
#define GPIO_PIN_4 ((uint16_t)0x0010U) /* Pin 4 selected */
|
||||||
|
#define GPIO_PIN_5 ((uint16_t)0x0020U) /* Pin 5 selected */
|
||||||
|
#define GPIO_PIN_6 ((uint16_t)0x0040U) /* Pin 6 selected */
|
||||||
|
#define GPIO_PIN_7 ((uint16_t)0x0080U) /* Pin 7 selected */
|
||||||
|
#define GPIO_PIN_8 ((uint16_t)0x0100U) /* Pin 8 selected */
|
||||||
|
#define GPIO_PIN_9 ((uint16_t)0x0200U) /* Pin 9 selected */
|
||||||
|
#define GPIO_PIN_10 ((uint16_t)0x0400U) /* Pin 10 selected */
|
||||||
|
#define GPIO_PIN_11 ((uint16_t)0x0800U) /* Pin 11 selected */
|
||||||
|
#define GPIO_PIN_12 ((uint16_t)0x1000U) /* Pin 12 selected */
|
||||||
|
#define GPIO_PIN_13 ((uint16_t)0x2000U) /* Pin 13 selected */
|
||||||
|
#define GPIO_PIN_14 ((uint16_t)0x4000U) /* Pin 14 selected */
|
||||||
|
#define GPIO_PIN_15 ((uint16_t)0x8000U) /* Pin 15 selected */
|
||||||
|
#define GPIO_PIN_All ((uint16_t)0xFFFFU) /* All pins selected */
|
||||||
|
|
||||||
|
#define GPIO_PIN_MASK ((uint32_t)0x0000FFFFU) /* PIN mask for assert test */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_mode_define GPIO mode define
|
||||||
|
* @brief GPIO Configuration Mode
|
||||||
|
* Elements values convention: 0xX0yz00YZ
|
||||||
|
* - X : GPIO mode or EXTI Mode
|
||||||
|
* - y : External IT or Event trigger detection
|
||||||
|
* - z : IO configuration on External IT or Event
|
||||||
|
* - Y : Output type (Push Pull or Open Drain)
|
||||||
|
* - Z : IO Direction mode (Input, Output, Alternate or Analog)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GPIO_MODE_INPUT ((uint32_t)0x00000000U) /*!< Input Floating Mode */
|
||||||
|
#define GPIO_MODE_OUTPUT_PP ((uint32_t)0x00000001U) /*!< Output Push Pull Mode */
|
||||||
|
#define GPIO_MODE_OUTPUT_OD ((uint32_t)0x00000011U) /*!< Output Open Drain Mode */
|
||||||
|
#define GPIO_MODE_AF_PP ((uint32_t)0x00000002U) /*!< Alternate Function Push Pull Mode */
|
||||||
|
#define GPIO_MODE_AF_OD ((uint32_t)0x00000012U) /*!< Alternate Function Open Drain Mode */
|
||||||
|
|
||||||
|
#define GPIO_MODE_ANALOG ((uint32_t)0x00000003U) /*!< Analog Mode */
|
||||||
|
|
||||||
|
#define GPIO_MODE_IT_RISING ((uint32_t)0x10110000U) /*!< External Interrupt Mode with Rising edge trigger detection */
|
||||||
|
#define GPIO_MODE_IT_FALLING ((uint32_t)0x10210000U) /*!< External Interrupt Mode with Falling edge trigger detection */
|
||||||
|
#define GPIO_MODE_IT_RISING_FALLING ((uint32_t)0x10310000U) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */
|
||||||
|
|
||||||
|
#define GPIO_MODE_EVT_RISING ((uint32_t)0x10120000U) /*!< External Event Mode with Rising edge trigger detection */
|
||||||
|
#define GPIO_MODE_EVT_FALLING ((uint32_t)0x10220000U) /*!< External Event Mode with Falling edge trigger detection */
|
||||||
|
#define GPIO_MODE_EVT_RISING_FALLING ((uint32_t)0x10320000U) /*!< External Event Mode with Rising/Falling edge trigger detection */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_speed_define GPIO speed define
|
||||||
|
* @brief GPIO Output Maximum frequency
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GPIO_SPEED_FREQ_LOW ((uint32_t)0x00000000U) /*!< Low speed */
|
||||||
|
#define GPIO_SPEED_FREQ_MEDIUM ((uint32_t)0x00000001U) /*!< Medium speed */
|
||||||
|
#define GPIO_SPEED_FREQ_HIGH ((uint32_t)0x00000002U) /*!< Fast speed */
|
||||||
|
#define GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)0x00000003U) /*!< High speed */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_pull_define GPIO pull define
|
||||||
|
* @brief GPIO Pull-Up or Pull-Down Activation
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GPIO_NOPULL ((uint32_t)0x00000000U) /*!< No Pull-up or Pull-down activation */
|
||||||
|
#define GPIO_PULLUP ((uint32_t)0x00000001U) /*!< Pull-up activation */
|
||||||
|
#define GPIO_PULLDOWN ((uint32_t)0x00000002U) /*!< Pull-down activation */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported macro ------------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIO_Exported_Macros GPIO Exported Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether the specified EXTI line flag is set or not.
|
||||||
|
* @param __EXTI_LINE__ specifies the EXTI line flag to check.
|
||||||
|
* This parameter can be GPIO_PIN_x where x can be(0..15)
|
||||||
|
* @retval The new state of __EXTI_LINE__ (SET or RESET).
|
||||||
|
*/
|
||||||
|
#define __HAL_GPIO_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the EXTI's line pending flags.
|
||||||
|
* @param __EXTI_LINE__ specifies the EXTI lines flags to clear.
|
||||||
|
* This parameter can be any combination of GPIO_PIN_x where x can be (0..15)
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
#define __HAL_GPIO_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->PR = (__EXTI_LINE__))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether the specified EXTI line is asserted or not.
|
||||||
|
* @param __EXTI_LINE__ specifies the EXTI line to check.
|
||||||
|
* This parameter can be GPIO_PIN_x where x can be(0..15)
|
||||||
|
* @retval The new state of __EXTI_LINE__ (SET or RESET).
|
||||||
|
*/
|
||||||
|
#define __HAL_GPIO_EXTI_GET_IT(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the EXTI's line pending bits.
|
||||||
|
* @param __EXTI_LINE__ specifies the EXTI lines to clear.
|
||||||
|
* This parameter can be any combination of GPIO_PIN_x where x can be (0..15)
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
#define __HAL_GPIO_EXTI_CLEAR_IT(__EXTI_LINE__) (EXTI->PR = (__EXTI_LINE__))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates a Software interrupt on selected EXTI line.
|
||||||
|
* @param __EXTI_LINE__ specifies the EXTI line to check.
|
||||||
|
* This parameter can be GPIO_PIN_x where x can be(0..15)
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
#define __HAL_GPIO_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER |= (__EXTI_LINE__))
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include GPIO HAL Extension module */
|
||||||
|
#include "stm32f7xx_hal_gpio_ex.h"
|
||||||
|
|
||||||
|
/* Exported functions --------------------------------------------------------*/
|
||||||
|
/** @addtogroup GPIO_Exported_Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup GPIO_Exported_Functions_Group1
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* Initialization and de-initialization functions *****************************/
|
||||||
|
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
|
||||||
|
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup GPIO_Exported_Functions_Group2
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* IO operation functions *****************************************************/
|
||||||
|
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
|
||||||
|
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
|
||||||
|
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
|
||||||
|
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
|
||||||
|
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
|
||||||
|
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Private types -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
/* Private constants ---------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIO_Private_Constants GPIO Private Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private macros ------------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIO_Private_Macros GPIO Private Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define IS_GPIO_PIN_ACTION(ACTION) (((ACTION) == GPIO_PIN_RESET) || ((ACTION) == GPIO_PIN_SET))
|
||||||
|
#define IS_GPIO_PIN(__PIN__) ((((uint32_t)(__PIN__) & GPIO_PIN_MASK) != 0x00U))
|
||||||
|
#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_MODE_INPUT) ||\
|
||||||
|
((MODE) == GPIO_MODE_OUTPUT_PP) ||\
|
||||||
|
((MODE) == GPIO_MODE_OUTPUT_OD) ||\
|
||||||
|
((MODE) == GPIO_MODE_AF_PP) ||\
|
||||||
|
((MODE) == GPIO_MODE_AF_OD) ||\
|
||||||
|
((MODE) == GPIO_MODE_IT_RISING) ||\
|
||||||
|
((MODE) == GPIO_MODE_IT_FALLING) ||\
|
||||||
|
((MODE) == GPIO_MODE_IT_RISING_FALLING) ||\
|
||||||
|
((MODE) == GPIO_MODE_EVT_RISING) ||\
|
||||||
|
((MODE) == GPIO_MODE_EVT_FALLING) ||\
|
||||||
|
((MODE) == GPIO_MODE_EVT_RISING_FALLING) ||\
|
||||||
|
((MODE) == GPIO_MODE_ANALOG))
|
||||||
|
#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_SPEED_LOW) || ((SPEED) == GPIO_SPEED_MEDIUM) || \
|
||||||
|
((SPEED) == GPIO_SPEED_FAST) || ((SPEED) == GPIO_SPEED_HIGH))
|
||||||
|
#define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || ((PULL) == GPIO_PULLUP) || \
|
||||||
|
((PULL) == GPIO_PULLDOWN))
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private functions ---------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIO_Private_Functions GPIO Private Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __STM32F7xx_HAL_GPIO_H */
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,658 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx_hal_gpio_ex.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief Header file of GPIO HAL Extension module.
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© Copyright (c) 2017 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __STM32F7xx_HAL_GPIO_EX_H
|
||||||
|
#define __STM32F7xx_HAL_GPIO_EX_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "stm32f7xx_hal_def.h"
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_HAL_Driver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIOEx GPIOEx
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIOEx_Exported_Constants GPIO Exported Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup GPIO_Alternate_function_selection GPIO Alternate Function Selection
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/*--------------- STM32F74xxx/STM32F75xxx/STM32F76xxx/STM32F77xxx -------------*/
|
||||||
|
#if defined (STM32F745xx) || defined (STM32F746xx) || defined (STM32F756xx) || defined (STM32F765xx) || defined (STM32F767xx) ||\
|
||||||
|
defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx) || defined (STM32F750xx)
|
||||||
|
/**
|
||||||
|
* @brief AF 0 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */
|
||||||
|
#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */
|
||||||
|
#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */
|
||||||
|
#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 1 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF1_UART5 ((uint8_t)0x01U) /* UART5 Alternate Function mapping */
|
||||||
|
#define GPIO_AF1_I2C4 ((uint8_t)0x01U) /* I2C4 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 2 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 3 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_LPTIM1 ((uint8_t)0x03U) /* LPTIM1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_CEC ((uint8_t)0x03U) /* CEC Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF3_DFSDM1 ((uint8_t)0x03U) /* DFSDM1 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
/**
|
||||||
|
* @brief AF 4 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF4_I2C4 ((uint8_t)0x04U) /* I2C4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF4_CEC ((uint8_t)0x04U) /* CEC Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF4_USART1 ((uint8_t)0x04) /* USART1 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 5 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI5 ((uint8_t)0x05U) /* SPI5 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI6 ((uint8_t)0x05U) /* SPI6 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 6 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF6_SAI1 ((uint8_t)0x06U) /* SAI1 Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF6_UART4 ((uint8_t)0x06U) /* UART4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF6_DFSDM1 ((uint8_t)0x06U) /* DFSDM1 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 7 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_UART5 ((uint8_t)0x07U) /* UART5 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_SPDIFRX ((uint8_t)0x07U) /* SPDIF-RX Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_SPI2 ((uint8_t)0x07U) /* SPI2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_SPI3 ((uint8_t)0x07U) /* SPI3 Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF7_SPI6 ((uint8_t)0x07U) /* SPI6 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_DFSDM1 ((uint8_t)0x07U) /* DFSDM1 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 8 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_UART7 ((uint8_t)0x08U) /* UART7 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_UART8 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_SPDIFRX ((uint8_t)0x08U) /* SPIDIF-RX Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_SAI2 ((uint8_t)0x08U) /* SAI2 Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF8_SPI6 ((uint8_t)0x08U) /* SPI6 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 9 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_QUADSPI ((uint8_t)0x09U) /* QUADSPI Alternate Function mapping */
|
||||||
|
#if defined(STM32F746xx) || defined(STM32F756xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F750xx)
|
||||||
|
#define GPIO_AF9_LTDC ((uint8_t)0x09U) /* LCD-TFT Alternate Function mapping */
|
||||||
|
#endif /* STM32F746xx || STM32F756xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx || STM32F750xx */
|
||||||
|
#if defined(STM32F746xx) || defined(STM32F756xx) || defined(STM32F765xx) || defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F750xx)
|
||||||
|
#define GPIO_AF9_FMC ((uint8_t)0x09U) /* FMC Alternate Function mapping */
|
||||||
|
#endif /* STM32F746xx || STM32F756xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx || STM32F750xx */
|
||||||
|
/**
|
||||||
|
* @brief AF 10 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF10_OTG_FS ((uint8_t)0xAU) /* OTG_FS Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_OTG_HS ((uint8_t)0xAU) /* OTG_HS Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_QUADSPI ((uint8_t)0xAU) /* QUADSPI Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_SAI2 ((uint8_t)0xAU) /* SAI2 Alternate Function mapping */
|
||||||
|
#if defined (STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx)
|
||||||
|
#define GPIO_AF10_DFSDM1 ((uint8_t)0x0AU) /* DFSDM1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_SDMMC2 ((uint8_t)0x0AU) /* SDMMC2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_LTDC ((uint8_t)0x0AU) /* LCD-TFT Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 11 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */
|
||||||
|
#if defined(STM32F765xx) || defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx)
|
||||||
|
#define GPIO_AF11_CAN3 ((uint8_t)0x0BU) /* CAN3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF11_SDMMC2 ((uint8_t)0x0BU) /* SDMMC2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF11_I2C4 ((uint8_t)0x0BU) /* I2C4 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 12 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF12_FMC ((uint8_t)0xCU) /* FMC Alternate Function mapping */
|
||||||
|
#define GPIO_AF12_OTG_HS_FS ((uint8_t)0xCU) /* OTG HS configured in FS, Alternate Function mapping */
|
||||||
|
#define GPIO_AF12_SDMMC1 ((uint8_t)0xCU) /* SDMMC1 Alternate Function mapping */
|
||||||
|
#if defined(STM32F765xx) || defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx)
|
||||||
|
#define GPIO_AF12_MDIOS ((uint8_t)0xCU) /* SDMMC1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF12_UART7 ((uint8_t)0xCU) /* UART7 Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 13 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */
|
||||||
|
#if defined (STM32F769xx) || defined (STM32F779xx)
|
||||||
|
#define GPIO_AF13_DSI ((uint8_t)0x0DU) /* DSI Alternate Function mapping */
|
||||||
|
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
#if defined(STM32F746xx) || defined(STM32F756xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F750xx)
|
||||||
|
#define GPIO_AF13_LTDC ((uint8_t)0x0DU) /* LTDC Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 14 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF14_LTDC ((uint8_t)0x0EU) /* LCD-TFT Alternate Function mapping */
|
||||||
|
#endif /* STM32F746xx || STM32F756xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx || STM32F750xx */
|
||||||
|
/**
|
||||||
|
* @brief AF 15 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */
|
||||||
|
#endif /* STM32F745xx || STM32F746xx || STM32F756xx || STM32F765xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------------------- STM32F72xxx/STM32F73xxx -----------------------*/
|
||||||
|
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) || defined(STM32F730xx)
|
||||||
|
/**
|
||||||
|
* @brief AF 0 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */
|
||||||
|
#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */
|
||||||
|
#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */
|
||||||
|
#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 1 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 2 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 3 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */
|
||||||
|
#define GPIO_AF3_LPTIM1 ((uint8_t)0x03U) /* LPTIM1 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 4 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 5 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF5_SPI5 ((uint8_t)0x05U) /* SPI5 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 6 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF6_SAI1 ((uint8_t)0x06U) /* SAI1 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 7 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_UART5 ((uint8_t)0x07U) /* UART5 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_SPI2 ((uint8_t)0x07U) /* SPI2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF7_SPI3 ((uint8_t)0x07U) /* SPI3 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 8 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_UART7 ((uint8_t)0x08U) /* UART7 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_UART8 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */
|
||||||
|
#define GPIO_AF8_SAI2 ((uint8_t)0x08U) /* SAI2 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 9 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */
|
||||||
|
#define GPIO_AF9_QUADSPI ((uint8_t)0x09U) /* QUADSPI Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 10 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF10_OTG_FS ((uint8_t)0xAU) /* OTG_FS Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_OTG_HS ((uint8_t)0xAU) /* OTG_HS Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_QUADSPI ((uint8_t)0xAU) /* QUADSPI Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_SAI2 ((uint8_t)0xAU) /* SAI2 Alternate Function mapping */
|
||||||
|
#define GPIO_AF10_SDMMC2 ((uint8_t)0x0AU) /* SDMMC2 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 11 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF11_SDMMC2 ((uint8_t)0x0BU) /* SDMMC2 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 12 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF12_FMC ((uint8_t)0xCU) /* FMC Alternate Function mapping */
|
||||||
|
#define GPIO_AF12_OTG_HS_FS ((uint8_t)0xCU) /* OTG HS configured in FS, Alternate Function mapping */
|
||||||
|
#define GPIO_AF12_SDMMC1 ((uint8_t)0xCU) /* SDMMC1 Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 13 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF13_RNG ((uint8_t)0x0DU) /* RNG Alternate Function mapping */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AF 15 selection
|
||||||
|
*/
|
||||||
|
#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */
|
||||||
|
#endif /* STM32F722xx || STM32F723xx || STM32F732xx || STM32F733xx || STM32F730xx */
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported macro ------------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIOEx_Exported_Macros GPIO Exported Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Exported functions --------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIOEx_Exported_Functions GPIO Exported Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/* Private types -------------------------------------------------------------*/
|
||||||
|
/* Private variables ---------------------------------------------------------*/
|
||||||
|
/* Private constants ---------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIOEx_Private_Constants GPIO Private Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GPIO pin available on the platform
|
||||||
|
*/
|
||||||
|
/* Defines the available pins per GPIOs */
|
||||||
|
#define GPIOA_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOB_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOC_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOD_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOE_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOF_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOG_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOI_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOJ_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOH_PIN_AVAILABLE GPIO_PIN_All
|
||||||
|
#define GPIOK_PIN_AVAILABLE (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | \
|
||||||
|
GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private macros ------------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIOEx_Private_Macros GPIO Private Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** @defgroup GPIOEx_Get_Port_Index GPIO Get Port Index
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#if defined (STM32F745xx) || defined (STM32F746xx) || defined (STM32F756xx) || defined (STM32F765xx) ||\
|
||||||
|
defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx) ||\
|
||||||
|
defined (STM32F750xx)
|
||||||
|
#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\
|
||||||
|
((__GPIOx__) == (GPIOB))? 1U :\
|
||||||
|
((__GPIOx__) == (GPIOC))? 2U :\
|
||||||
|
((__GPIOx__) == (GPIOD))? 3U :\
|
||||||
|
((__GPIOx__) == (GPIOE))? 4U :\
|
||||||
|
((__GPIOx__) == (GPIOF))? 5U :\
|
||||||
|
((__GPIOx__) == (GPIOG))? 6U :\
|
||||||
|
((__GPIOx__) == (GPIOH))? 7U :\
|
||||||
|
((__GPIOx__) == (GPIOI))? 8U :\
|
||||||
|
((__GPIOx__) == (GPIOJ))? 9U : 10U)
|
||||||
|
#endif /* STM32F745xx || STM32F746xx || STM32F756xx || STM32F765xx || STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx || STM32F750xx */
|
||||||
|
|
||||||
|
#if defined (STM32F722xx) || defined (STM32F723xx) || defined (STM32F732xx) || defined (STM32F733xx) || defined (STM32F730xx)
|
||||||
|
#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\
|
||||||
|
((__GPIOx__) == (GPIOB))? 1U :\
|
||||||
|
((__GPIOx__) == (GPIOC))? 2U :\
|
||||||
|
((__GPIOx__) == (GPIOD))? 3U :\
|
||||||
|
((__GPIOx__) == (GPIOE))? 4U :\
|
||||||
|
((__GPIOx__) == (GPIOF))? 5U :\
|
||||||
|
((__GPIOx__) == (GPIOG))? 6U :\
|
||||||
|
((__GPIOx__) == (GPIOH))? 7U : 8U)
|
||||||
|
#endif /* STM32F722xx || STM32F723xx || STM32F732xx || STM32F733xx || STM32F730xx */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IS_GPIO_PIN_AVAILABLE(__INSTANCE__,__PIN__) \
|
||||||
|
((((__INSTANCE__) == GPIOA) && (((__PIN__) & (GPIOA_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOA_PIN_AVAILABLE)) == (GPIOA_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOB) && (((__PIN__) & (GPIOB_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOB_PIN_AVAILABLE)) == (GPIOB_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOC) && (((__PIN__) & (GPIOC_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOC_PIN_AVAILABLE)) == (GPIOC_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOD) && (((__PIN__) & (GPIOD_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOD_PIN_AVAILABLE)) == (GPIOD_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOE) && (((__PIN__) & (GPIOE_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOE_PIN_AVAILABLE)) == (GPIOE_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOF) && (((__PIN__) & (GPIOF_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOF_PIN_AVAILABLE)) == (GPIOF_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOG) && (((__PIN__) & (GPIOG_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOG_PIN_AVAILABLE)) == (GPIOG_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOI) && (((__PIN__) & (GPIOI_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOI_PIN_AVAILABLE)) == (GPIOI_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOJ) && (((__PIN__) & (GPIOJ_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOJ_PIN_AVAILABLE)) == (GPIOJ_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOK) && (((__PIN__) & (GPIOK_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOK_PIN_AVAILABLE)) == (GPIOK_PIN_AVAILABLE))) || \
|
||||||
|
(((__INSTANCE__) == GPIOH) && (((__PIN__) & (GPIOH_PIN_AVAILABLE)) != 0) && (((__PIN__) | (GPIOH_PIN_AVAILABLE)) == (GPIOH_PIN_AVAILABLE))))
|
||||||
|
/** @defgroup GPIOEx_IS_Alternat_function_selection GPIO Check Alternate Function
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#if defined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F750xx)
|
||||||
|
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF1_TIM1) || \
|
||||||
|
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||||
|
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF1_TIM2) || \
|
||||||
|
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||||
|
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||||
|
((AF) == GPIO_AF3_TIM9) || ((AF) == GPIO_AF3_TIM10) || \
|
||||||
|
((AF) == GPIO_AF3_TIM11) || ((AF) == GPIO_AF3_LPTIM1) || \
|
||||||
|
((AF) == GPIO_AF3_CEC) || ((AF) == GPIO_AF4_CEC) || \
|
||||||
|
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||||
|
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF4_I2C4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \
|
||||||
|
((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF5_SPI4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \
|
||||||
|
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF6_SAI1) || \
|
||||||
|
((AF) == GPIO_AF7_SPI3) || ((AF) == GPIO_AF7_SPI2) || \
|
||||||
|
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||||
|
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF7_UART5) || \
|
||||||
|
((AF) == GPIO_AF7_SPDIFRX) || ((AF) == GPIO_AF8_SPDIFRX) || \
|
||||||
|
((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF8_USART6) || \
|
||||||
|
((AF) == GPIO_AF8_UART4) || ((AF) == GPIO_AF8_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \
|
||||||
|
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||||
|
((AF) == GPIO_AF9_TIM12) || ((AF) == GPIO_AF9_TIM12) || \
|
||||||
|
((AF) == GPIO_AF9_TIM14) || ((AF) == GPIO_AF9_QUADSPI) || \
|
||||||
|
((AF) == GPIO_AF9_LTDC) || ((AF) == GPIO_AF10_OTG_FS) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_HS) || ((AF) == GPIO_AF10_SAI2) || \
|
||||||
|
((AF) == GPIO_AF10_QUADSPI) || ((AF) == GPIO_AF11_ETH) || \
|
||||||
|
((AF) == GPIO_AF12_OTG_HS_FS) || ((AF) == GPIO_AF12_SDMMC1) || \
|
||||||
|
((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF15_EVENTOUT) || \
|
||||||
|
((AF) == GPIO_AF13_DCMI) || ((AF) == GPIO_AF14_LTDC))
|
||||||
|
#elif defined(STM32F745xx)
|
||||||
|
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF1_TIM1) || \
|
||||||
|
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||||
|
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF1_TIM2) || \
|
||||||
|
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||||
|
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||||
|
((AF) == GPIO_AF3_TIM9) || ((AF) == GPIO_AF3_TIM10) || \
|
||||||
|
((AF) == GPIO_AF3_TIM11) || ((AF) == GPIO_AF3_LPTIM1) || \
|
||||||
|
((AF) == GPIO_AF3_CEC) || ((AF) == GPIO_AF4_CEC) || \
|
||||||
|
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||||
|
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF4_I2C4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \
|
||||||
|
((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF5_SPI4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \
|
||||||
|
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF6_SAI1) || \
|
||||||
|
((AF) == GPIO_AF7_SPI3) || ((AF) == GPIO_AF7_SPI2) || \
|
||||||
|
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||||
|
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF7_UART5) || \
|
||||||
|
((AF) == GPIO_AF7_SPDIFRX) || ((AF) == GPIO_AF8_SPDIFRX) || \
|
||||||
|
((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF8_USART6) || \
|
||||||
|
((AF) == GPIO_AF8_UART4) || ((AF) == GPIO_AF8_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \
|
||||||
|
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||||
|
((AF) == GPIO_AF9_TIM12) || ((AF) == GPIO_AF9_TIM12) || \
|
||||||
|
((AF) == GPIO_AF9_TIM14) || ((AF) == GPIO_AF9_QUADSPI) || \
|
||||||
|
((AF) == GPIO_AF13_DCMI) || ((AF) == GPIO_AF10_OTG_FS) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_HS) || ((AF) == GPIO_AF10_SAI2) || \
|
||||||
|
((AF) == GPIO_AF10_QUADSPI) || ((AF) == GPIO_AF11_ETH) || \
|
||||||
|
((AF) == GPIO_AF12_OTG_HS_FS) || ((AF) == GPIO_AF12_SDMMC1) || \
|
||||||
|
((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF15_EVENTOUT))
|
||||||
|
#elif defined(STM32F767xx) || defined(STM32F777xx)
|
||||||
|
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF1_TIM1) || \
|
||||||
|
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||||
|
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF1_TIM2) || \
|
||||||
|
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||||
|
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||||
|
((AF) == GPIO_AF3_TIM9) || ((AF) == GPIO_AF3_TIM10) || \
|
||||||
|
((AF) == GPIO_AF3_TIM11) || ((AF) == GPIO_AF3_LPTIM1) || \
|
||||||
|
((AF) == GPIO_AF3_CEC) || ((AF) == GPIO_AF4_CEC) || \
|
||||||
|
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||||
|
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF4_I2C4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \
|
||||||
|
((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF5_SPI4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \
|
||||||
|
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF6_SAI1) || \
|
||||||
|
((AF) == GPIO_AF7_SPI3) || ((AF) == GPIO_AF7_SPI2) || \
|
||||||
|
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||||
|
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF7_UART5) || \
|
||||||
|
((AF) == GPIO_AF7_SPDIFRX) || ((AF) == GPIO_AF8_SPDIFRX) || \
|
||||||
|
((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF8_USART6) || \
|
||||||
|
((AF) == GPIO_AF8_UART4) || ((AF) == GPIO_AF8_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \
|
||||||
|
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||||
|
((AF) == GPIO_AF9_TIM12) || ((AF) == GPIO_AF9_TIM12) || \
|
||||||
|
((AF) == GPIO_AF9_TIM14) || ((AF) == GPIO_AF9_QUADSPI) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF9_LTDC) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_HS) || ((AF) == GPIO_AF10_SAI2) || \
|
||||||
|
((AF) == GPIO_AF10_QUADSPI) || ((AF) == GPIO_AF11_ETH) || \
|
||||||
|
((AF) == GPIO_AF10_SDMMC2) || ((AF) == GPIO_AF11_SDMMC2) || \
|
||||||
|
((AF) == GPIO_AF11_CAN3) || ((AF) == GPIO_AF12_OTG_HS_FS) || \
|
||||||
|
((AF) == GPIO_AF12_SDMMC1) || ((AF) == GPIO_AF12_FMC) || \
|
||||||
|
((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF13_DCMI) || \
|
||||||
|
((AF) == GPIO_AF14_LTDC))
|
||||||
|
#elif defined(STM32F769xx) || defined(STM32F779xx)
|
||||||
|
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF1_TIM1) || \
|
||||||
|
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||||
|
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF1_TIM2) || \
|
||||||
|
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||||
|
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||||
|
((AF) == GPIO_AF3_TIM9) || ((AF) == GPIO_AF3_TIM10) || \
|
||||||
|
((AF) == GPIO_AF3_TIM11) || ((AF) == GPIO_AF3_LPTIM1) || \
|
||||||
|
((AF) == GPIO_AF3_CEC) || ((AF) == GPIO_AF4_CEC) || \
|
||||||
|
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||||
|
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF4_I2C4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \
|
||||||
|
((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF5_SPI4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \
|
||||||
|
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF6_SAI1) || \
|
||||||
|
((AF) == GPIO_AF7_SPI3) || ((AF) == GPIO_AF7_SPI2) || \
|
||||||
|
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||||
|
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF7_UART5) || \
|
||||||
|
((AF) == GPIO_AF7_SPDIFRX) || ((AF) == GPIO_AF8_SPDIFRX) || \
|
||||||
|
((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF8_USART6) || \
|
||||||
|
((AF) == GPIO_AF8_UART4) || ((AF) == GPIO_AF8_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \
|
||||||
|
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||||
|
((AF) == GPIO_AF9_TIM12) || ((AF) == GPIO_AF9_TIM12) || \
|
||||||
|
((AF) == GPIO_AF9_TIM14) || ((AF) == GPIO_AF9_QUADSPI) || \
|
||||||
|
((AF) == GPIO_AF9_LTDC) || ((AF) == GPIO_AF10_OTG_FS) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_HS) || ((AF) == GPIO_AF10_SAI2) || \
|
||||||
|
((AF) == GPIO_AF10_QUADSPI) || ((AF) == GPIO_AF11_ETH) || \
|
||||||
|
((AF) == GPIO_AF10_SDMMC2) || ((AF) == GPIO_AF11_SDMMC2) || \
|
||||||
|
((AF) == GPIO_AF11_CAN3) || ((AF) == GPIO_AF12_OTG_HS_FS) || \
|
||||||
|
((AF) == GPIO_AF12_SDMMC1) || ((AF) == GPIO_AF12_FMC) || \
|
||||||
|
((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF13_DCMI) || \
|
||||||
|
((AF) == GPIO_AF14_LTDC) || ((AF) == GPIO_AF13_DSI))
|
||||||
|
#elif defined(STM32F765xx)
|
||||||
|
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF1_TIM1) || \
|
||||||
|
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||||
|
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF1_TIM2) || \
|
||||||
|
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||||
|
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||||
|
((AF) == GPIO_AF3_TIM9) || ((AF) == GPIO_AF3_TIM10) || \
|
||||||
|
((AF) == GPIO_AF3_TIM11) || ((AF) == GPIO_AF3_LPTIM1) || \
|
||||||
|
((AF) == GPIO_AF3_CEC) || ((AF) == GPIO_AF4_CEC) || \
|
||||||
|
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||||
|
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF4_I2C4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \
|
||||||
|
((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF5_SPI4) || \
|
||||||
|
((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \
|
||||||
|
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF6_SAI1) || \
|
||||||
|
((AF) == GPIO_AF7_SPI3) || ((AF) == GPIO_AF7_SPI2) || \
|
||||||
|
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||||
|
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF7_UART5) || \
|
||||||
|
((AF) == GPIO_AF7_SPDIFRX) || ((AF) == GPIO_AF8_SPDIFRX) || \
|
||||||
|
((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF8_USART6) || \
|
||||||
|
((AF) == GPIO_AF8_UART4) || ((AF) == GPIO_AF8_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \
|
||||||
|
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \
|
||||||
|
((AF) == GPIO_AF9_TIM12) || ((AF) == GPIO_AF9_TIM12) || \
|
||||||
|
((AF) == GPIO_AF9_TIM14) || ((AF) == GPIO_AF9_QUADSPI) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_HS) || ((AF) == GPIO_AF10_SAI2) || \
|
||||||
|
((AF) == GPIO_AF10_QUADSPI) || ((AF) == GPIO_AF11_ETH) || \
|
||||||
|
((AF) == GPIO_AF10_SDMMC2) || ((AF) == GPIO_AF11_SDMMC2) || \
|
||||||
|
((AF) == GPIO_AF11_CAN3) || ((AF) == GPIO_AF12_OTG_HS_FS) || \
|
||||||
|
((AF) == GPIO_AF12_SDMMC1) || ((AF) == GPIO_AF12_FMC) || \
|
||||||
|
((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF13_DCMI) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_FS))
|
||||||
|
#elif defined (STM32F722xx) || defined (STM32F723xx) || defined (STM32F732xx) || defined (STM32F733xx) || defined (STM32F730xx)
|
||||||
|
#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF1_TIM1) || \
|
||||||
|
((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \
|
||||||
|
((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF1_TIM2) || \
|
||||||
|
((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \
|
||||||
|
((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \
|
||||||
|
((AF) == GPIO_AF3_TIM9) || ((AF) == GPIO_AF3_TIM10) || \
|
||||||
|
((AF) == GPIO_AF3_TIM11) || ((AF) == GPIO_AF3_LPTIM1) || \
|
||||||
|
((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \
|
||||||
|
((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \
|
||||||
|
((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF5_SPI3) || \
|
||||||
|
((AF) == GPIO_AF5_SPI4) || ((AF) == GPIO_AF5_SPI5) || \
|
||||||
|
((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF6_SAI1) || \
|
||||||
|
((AF) == GPIO_AF7_SPI3) || ((AF) == GPIO_AF7_SPI2) || \
|
||||||
|
((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \
|
||||||
|
((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF7_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF8_USART6) || \
|
||||||
|
((AF) == GPIO_AF8_UART4) || ((AF) == GPIO_AF8_UART5) || \
|
||||||
|
((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \
|
||||||
|
((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_TIM12) || \
|
||||||
|
((AF) == GPIO_AF9_TIM12) || ((AF) == GPIO_AF9_TIM14) || \
|
||||||
|
((AF) == GPIO_AF9_QUADSPI) || ((AF) == GPIO_AF10_OTG_HS) || \
|
||||||
|
((AF) == GPIO_AF10_SAI2) || ((AF) == GPIO_AF10_QUADSPI) || \
|
||||||
|
((AF) == GPIO_AF10_SDMMC2) || ((AF) == GPIO_AF11_SDMMC2) || \
|
||||||
|
((AF) == GPIO_AF12_OTG_HS_FS) || ((AF) == GPIO_AF12_SDMMC1) || \
|
||||||
|
((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF15_EVENTOUT) || \
|
||||||
|
((AF) == GPIO_AF10_OTG_FS))
|
||||||
|
#endif /* STM32F756xx || STM32F746xx || STM32F750xx */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private functions ---------------------------------------------------------*/
|
||||||
|
/** @defgroup GPIOEx_Private_Functions GPIO Private Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __STM32F7xx_HAL_GPIO_EX_H */
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,95 @@
|
|||||||
|
# FreeRTOS/{FreeRTOS-Kernel V10.4.3,FreeRTOS-Plus-TCP V2.3.2}
|
||||||
|
PROG = firmware
|
||||||
|
ARCH = stm32f7
|
||||||
|
PROJECT_ROOT_PATH = $(realpath $(CURDIR)/../..)
|
||||||
|
DOCKER ?= docker run -it --rm -v $(PROJECT_ROOT_PATH):$(PROJECT_ROOT_PATH) -w $(CURDIR) mdashnet/armgcc
|
||||||
|
FREERTOS_KERNEL_PATH ?= $(PROJECT_ROOT_PATH)/test/freertos-kernel
|
||||||
|
FREERTOS_PLUS_TCP_PATH ?= $(PROJECT_ROOT_PATH)/test/freertos-tcp
|
||||||
|
|
||||||
|
MONGOOSE_FLAGS = -DMG_ARCH=MG_ARCH_FREERTOS_TCP -DMG_ENABLE_FS=1
|
||||||
|
MCU_FLAGS = -mcpu=cortex-m7 -mthumb -mfloat-abi=softfp -mfpu=vfpv4
|
||||||
|
#-mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard
|
||||||
|
|
||||||
|
INCLUDES = -I$(PROJECT_ROOT_PATH) -I$(ARCH) -I$(FREERTOS_KERNEL_PATH)/include -I$(FREERTOS_PLUS_TCP_PATH)/include
|
||||||
|
INCLUDES += -I$(FREERTOS_PLUS_TCP_PATH)/tools/tcp_utilities/include
|
||||||
|
INCLUDES += -I$(FREERTOS_PLUS_TCP_PATH)/../Utilities/include
|
||||||
|
#INCLUDES += -IH2
|
||||||
|
#INCLUDES += -I/Users/lsm/src/htibosch/plus/stm32F7/ST_Library/include
|
||||||
|
INCLUDES += -IHAL
|
||||||
|
INCLUDES += -I$(FREERTOS_PLUS_TCP_PATH)/portable/Compiler/GCC
|
||||||
|
INCLUDES += -I$(FREERTOS_PLUS_TCP_PATH)/portable/NetworkInterface/STM32Fxx
|
||||||
|
INCLUDES += -I$(FREERTOS_PLUS_TCP_PATH)/portable/NetworkInterface/include
|
||||||
|
NETFLAGS = -DSTM32F7xx -DSTM32F746xx -Wno-sign-compare -Wno-unused-function #-Wno-cpp
|
||||||
|
|
||||||
|
CFLAGS = -g3 -O0 -W -Wall $(MCU_FLAGS)
|
||||||
|
CFLAGS += $(INCLUDES) $(MONGOOSE_FLAGS) $(NETFLAGS) $(EXTRA)
|
||||||
|
|
||||||
|
LINKFLAGS = -T$(ARCH)/link.ld -mcpu=cortex-m7 -mthumb -nostartfiles --specs rdimon.specs -Wl,--gc-sections
|
||||||
|
|
||||||
|
SOURCES = main.c $(PROJECT_ROOT_PATH)/mongoose.c
|
||||||
|
SOURCES += $(wildcard HAL/*.c)
|
||||||
|
#SOURCES += -I$(realpath $(FREERTOS_KERNEL_PATH)/../../stm32F7/ST_Library/sources)/
|
||||||
|
|
||||||
|
# FreeRTOS kernel sources
|
||||||
|
SOURCES += $(wildcard $(FREERTOS_KERNEL_PATH)/*.c)
|
||||||
|
SOURCES += $(FREERTOS_KERNEL_PATH)/portable/MemMang/heap_5.c
|
||||||
|
SOURCES += $(FREERTOS_KERNEL_PATH)/portable/GCC/ARM_CM7/r0p1/port.c
|
||||||
|
|
||||||
|
# FreeRTOS TCP stack sources
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_ARP.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_DHCP.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_DNS.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_IP.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_Sockets.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_Stream_Buffer.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_TCP_IP.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_TCP_WIN.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/FreeRTOS_UDP_IP.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/portable/NetworkInterface/Common/phyHandling.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/portable/BufferManagement/BufferAllocation_1.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
|
||||||
|
SOURCES += $(FREERTOS_PLUS_TCP_PATH)/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c
|
||||||
|
|
||||||
|
OBJECTS = obj/boot.o $(SOURCES:%.c=obj/%.o)
|
||||||
|
|
||||||
|
all: $(PROG).hex
|
||||||
|
|
||||||
|
$(PROG).bin: $(PROG).elf
|
||||||
|
$(DOCKER) arm-none-eabi-objcopy -O binary $< $@
|
||||||
|
|
||||||
|
$(PROG).hex: $(PROG).bin
|
||||||
|
$(DOCKER) arm-none-eabi-objcopy -I binary -O ihex --change-address 0x8000000 $< $@
|
||||||
|
|
||||||
|
$(PROG).elf: $(OBJECTS) Makefile
|
||||||
|
$(DOCKER) arm-none-eabi-gcc $(OBJECTS) $(LINKFLAGS) -o $@
|
||||||
|
$(DOCKER) arm-none-eabi-size -A $@
|
||||||
|
|
||||||
|
obj/%.o: %.c
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(DOCKER) arm-none-eabi-gcc $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
obj/boot.o: $(ARCH)/boot.s
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(DOCKER) arm-none-eabi-as -g3 --warn --fatal-warnings $(MCU_FLAGS) $< -o $@
|
||||||
|
|
||||||
|
flash: $(PROG).bin
|
||||||
|
st-flash --reset write $< 0x8000000
|
||||||
|
|
||||||
|
openocd:
|
||||||
|
openocd -f openocd.cfg
|
||||||
|
|
||||||
|
ELF ?= $(PROG).elf
|
||||||
|
gdb: #$(PROG).elf
|
||||||
|
arm-none-eabi-gdb \
|
||||||
|
-ex 'set confirm off' \
|
||||||
|
-ex 'target extended-remote :3333' \
|
||||||
|
-ex 'monitor arm semihosting enable' \
|
||||||
|
-ex 'monitor reset halt' \
|
||||||
|
-ex 'load' \
|
||||||
|
-ex 'monitor reset init' \
|
||||||
|
-ex '$(GDBCMD)' \
|
||||||
|
-ex 'r' \
|
||||||
|
$(ELF)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -rf *.{bin,elf,map,lst,tgz,zip,hex} obj
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Mongoose with STM32, FreeRTOS kernel and FreeRTOS-TCP network stack
|
||||||
|
|
||||||
|
The `-DMG_ARCH=MG_ARCH_FREERTOS_TCP` compilation flag enables FreeRTOS+TCP support.
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
// Copyright (c) 2021 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static const char *s_debug_level = "4";
|
||||||
|
static const char *s_listening_address = "http://0.0.0.0:80";
|
||||||
|
|
||||||
|
// Event handler for the listening connection.
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
#if MG_ENABLE_FS
|
||||||
|
struct mg_http_serve_opts opts = {.root_dir = "/"};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
#else
|
||||||
|
mg_http_reply(c, 200, "", "hello, %s!\n", "world");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
(void) ev_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server(void *args) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
mg_log_set(s_debug_level);
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
LOG(LL_INFO, ("Starting Mongoose v%s", MG_VERSION)); // Tell the world
|
||||||
|
mg_http_listen(&mgr, s_listening_address, cb, &mgr); // Web listener
|
||||||
|
while (args == NULL) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
|
mg_mgr_free(&mgr); // Unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blinker(void *args) {
|
||||||
|
uint16_t pin = ((char *) args)[0] == '1' ? LED2 : LED3;
|
||||||
|
int ms = pin == LED2 ? 3750 : 5130;
|
||||||
|
for (;;) {
|
||||||
|
gpio_toggle(pin);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(ms));
|
||||||
|
LOG(LL_INFO, ("blink %s, RAM: %u", (char *) args, xPortGetFreeHeapSize()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Mongoose server when network is ready
|
||||||
|
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t ev) {
|
||||||
|
static bool mongoose_started = false;
|
||||||
|
LOG(LL_INFO, ("FreeRTOS net event %d, up: %d", ev, eNetworkUp));
|
||||||
|
if (ev == eNetworkUp && mongoose_started == false) {
|
||||||
|
xTaskCreate(server, "server", 8192, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||||
|
mongoose_started = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_heap(void) {
|
||||||
|
extern uint32_t _end, _estack;
|
||||||
|
uint8_t *ptr = (uint8_t *) ((((uint32_t) &_end) + 7) & ~7U);
|
||||||
|
uint32_t len = (uint32_t)((char *) &_estack - (char *) &_end);
|
||||||
|
HeapRegion_t regions[] = {{ptr, len}, {NULL, 0}};
|
||||||
|
vPortDefineHeapRegions(regions);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
init_hardware();
|
||||||
|
init_heap();
|
||||||
|
|
||||||
|
// Initialise networking task. Can be done before scheduler is started
|
||||||
|
static const uint8_t macaddr[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
|
||||||
|
static const uint8_t ipaddr[4] = {192, 168, 0, 77};
|
||||||
|
static const uint8_t netmask[4] = {255, 255, 255, 0};
|
||||||
|
static const uint8_t dnsaddr[4] = {8, 8, 8, 8};
|
||||||
|
static const uint8_t gwaddr[4] = {192, 168, 0, 1};
|
||||||
|
FreeRTOS_IPInit(ipaddr, netmask, gwaddr, dnsaddr, macaddr);
|
||||||
|
|
||||||
|
xTaskCreate(blinker, "blinker", 512, "1", configMAX_PRIORITIES - 1, NULL);
|
||||||
|
xTaskCreate(blinker, "blinker", 512, "2", configMAX_PRIORITIES - 1, NULL);
|
||||||
|
vTaskStartScheduler(); // This blocks
|
||||||
|
return 0; // Unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stubs for FreeRTOS-TCP network interface
|
||||||
|
uint32_t ulApplicationGetNextSequenceNumber(uint32_t a, uint16_t b, uint32_t c,
|
||||||
|
uint16_t d) {
|
||||||
|
return a ^ b ^ c ^ d;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xApplicationGetRandomNumber(uint32_t *p) {
|
||||||
|
*p = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SystemCoreClock = 216000000;
|
||||||
|
uint32_t HAL_RCC_GetHCLKFreq(void) {
|
||||||
|
return SystemCoreClock;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HAL_GetTick(void) {
|
||||||
|
return configTICK_RATE_HZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "stm32f7xx_hal_conf.h"
|
||||||
|
#include "stm32fxx_hal_eth.h"
|
||||||
|
void HAL_ETH_MspInit( ETH_HandleTypeDef* heth ) {
|
||||||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
|
if (heth->Instance == ETH) {
|
||||||
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||||
|
|
||||||
|
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||||
|
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||||
|
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||||
|
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||||
|
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
|
||||||
|
HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
|
||||||
|
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||||
|
|
||||||
|
__HAL_RCC_ETH_CLK_ENABLE();
|
||||||
|
HAL_NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_4 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vLoggingPrintf(const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
char buf[100];
|
||||||
|
int n = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
write(1, buf, n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *_sbrk(ptrdiff_t incr) {
|
||||||
|
(void) incr;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
source [find interface/stlink-v2-1.cfg]
|
||||||
|
transport select hla_swd
|
||||||
|
source [find target/stm32f7x.cfg]
|
||||||
|
reset_config srst_only srst_nogate
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define configUSE_PREEMPTION 1
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#define configCPU_CLOCK_HZ ((unsigned long) 216000000)
|
||||||
|
#define configSYSTICK_CLOCK_HZ (configCPU_CLOCK_HZ / 8)
|
||||||
|
#define configTICK_RATE_HZ 250
|
||||||
|
#define configMAX_PRIORITIES 5
|
||||||
|
#define configMINIMAL_STACK_SIZE 512
|
||||||
|
#define configMAX_TASK_NAME_LEN 16
|
||||||
|
#define configUSE_16_BIT_TICKS 0
|
||||||
|
#define configIDLE_SHOULD_YIELD 1
|
||||||
|
#define configUSE_TASK_NOTIFICATIONS 1
|
||||||
|
#define configUSE_MUTEXES 1
|
||||||
|
#define configUSE_RECURSIVE_MUTEXES 1
|
||||||
|
#define configUSE_COUNTING_SEMAPHORES 1
|
||||||
|
#define configQUEUE_REGISTRY_SIZE 8
|
||||||
|
|
||||||
|
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||||
|
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||||
|
|
||||||
|
#define configUSE_IDLE_HOOK 0
|
||||||
|
#define configUSE_TICK_HOOK 0
|
||||||
|
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||||
|
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||||
|
|
||||||
|
#define configGENERATE_RUN_TIME_STATS 0
|
||||||
|
#define configUSE_TRACE_FACILITY 0
|
||||||
|
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||||
|
|
||||||
|
#define configUSE_CO_ROUTINES 0
|
||||||
|
#define configMAX_CO_ROUTINE_PRIORITIES 1
|
||||||
|
|
||||||
|
#define configUSE_TIMERS 0
|
||||||
|
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
|
||||||
|
#define configTIMER_QUEUE_LENGTH 10
|
||||||
|
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
#ifdef __NVIC_PRIO_BITS
|
||||||
|
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||||
|
#else
|
||||||
|
#define configPRIO_BITS 4
|
||||||
|
#endif
|
||||||
|
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
|
||||||
|
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 4
|
||||||
|
#define configKERNEL_INTERRUPT_PRIORITY \
|
||||||
|
(configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
|
||||||
|
#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
|
||||||
|
(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
|
||||||
|
|
||||||
|
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
|
||||||
|
|
||||||
|
#define INCLUDE_vTaskPrioritySet 1
|
||||||
|
#define INCLUDE_uxTaskPriorityGet 1
|
||||||
|
#define INCLUDE_vTaskDelete 1
|
||||||
|
#define INCLUDE_vTaskCleanUpResources 0
|
||||||
|
#define INCLUDE_vTaskSuspend 1
|
||||||
|
#define INCLUDE_vTaskDelayUntil 0
|
||||||
|
#define INCLUDE_vTaskDelay 1
|
||||||
|
#define INCLUDE_xTimerPendFunctionCall 0
|
||||||
|
#define INCLUDE_eTaskGetState 1
|
||||||
|
#define INCLUDE_pcTaskGetTaskName 1
|
||||||
|
#define INCLUDE_xTaskGetSchedulerState 1
|
||||||
|
|
||||||
|
#define vPortSVCHandler SVC_Handler
|
||||||
|
#define xPortPendSVHandler PendSV_Handler
|
||||||
|
#define xPortSysTickHandler SysTick_Handler
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
#define FREERTOS_IP_CONFIG_H
|
||||||
|
|
||||||
|
#ifndef ipconfigHAS_DEBUG_PRINTF
|
||||||
|
#define ipconfigHAS_DEBUG_PRINTF 1
|
||||||
|
#endif
|
||||||
|
#if (ipconfigHAS_DEBUG_PRINTF == 1)
|
||||||
|
#define FreeRTOS_debug_printf(X) vLoggingPrintf X
|
||||||
|
#endif
|
||||||
|
#ifndef ipconfigHAS_PRINTF
|
||||||
|
#define ipconfigHAS_PRINTF 1
|
||||||
|
#endif
|
||||||
|
#if (ipconfigHAS_PRINTF == 1)
|
||||||
|
#define FreeRTOS_printf(X) vLoggingPrintf X
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN
|
||||||
|
#define ipconfigREPLY_TO_INCOMING_PINGS 1
|
||||||
|
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM (1)
|
||||||
|
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM (1)
|
||||||
|
#define ipconfigZERO_COPY_RX_DRIVER (1)
|
||||||
|
#define ipconfigZERO_COPY_TX_DRIVER (1)
|
||||||
|
#define ipconfigIP_TASK_PRIORITY 4
|
||||||
|
#define niEMAC_HANDLER_TASK_PRIORITY 5
|
||||||
|
#define ipconfigIPERF_PRIORITY_IPERF_TASK 6
|
||||||
|
#define ipconfigIP_TASK_STACK_SIZE_WORDS (configMINIMAL_STACK_SIZE * 5)
|
||||||
|
extern UBaseType_t uxRand();
|
||||||
|
#define ipconfigRAND32() uxRand()
|
||||||
|
#define ipconfigUSE_NETWORK_EVENT_HOOK 1
|
||||||
|
#define ipconfigUSE_DHCP 0
|
||||||
|
#define ipconfigDHCP_REGISTER_HOSTNAME 0
|
||||||
|
#define ipconfigDHCP_USES_UNICAST 1
|
||||||
|
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD (pdMS_TO_TICKS(30000))
|
||||||
|
#define ipconfigARP_CACHE_ENTRIES 6
|
||||||
|
#define ipconfigMAX_ARP_RETRANSMISSIONS (5)
|
||||||
|
#define ipconfigMAX_ARP_AGE 150
|
||||||
|
#define ipconfigINCLUDE_FULL_INET_ADDR 0
|
||||||
|
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 20
|
||||||
|
#define ipconfigEVENT_QUEUE_LENGTH (ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5)
|
||||||
|
#define ipconfigUDP_TIME_TO_LIVE 128
|
||||||
|
#define ipconfigTCP_TIME_TO_LIVE 128
|
||||||
|
#define ipconfigUSE_TCP 1
|
||||||
|
#define ipconfigSUPPORT_SELECT_FUNCTION 1
|
||||||
|
#define ipconfigUSE_TCP_WIN 0
|
||||||
|
#define ipconfigNETWORK_MTU 1500
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
.cpu cortex-m7
|
||||||
|
.fpu softvfp
|
||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
.section .vectortab,"a",%progbits
|
||||||
|
// Cortex-M7 interrupt handlers
|
||||||
|
.word _estack // 0 Stack top address
|
||||||
|
.word _reset // 1 Reset
|
||||||
|
.word pass // 2 NMI
|
||||||
|
.word halt // 3 Hard Fault
|
||||||
|
.word halt // 4 MM Fault
|
||||||
|
.word halt // 5 Bus Fault
|
||||||
|
.word halt // 6 Usage Fault
|
||||||
|
.word 0 // 7 RESERVED
|
||||||
|
.word 0 // 8 RESERVED
|
||||||
|
.word 0 // 9 RESERVED
|
||||||
|
.word 0 // 10 RESERVED
|
||||||
|
.word SVC_Handler // 11 SV call
|
||||||
|
.word halt // 12 Debug reserved
|
||||||
|
.word 0 // 13 RESERVED
|
||||||
|
.word PendSV_Handler // 14 PendSV
|
||||||
|
.word SysTick_Handler // 15 SysTick
|
||||||
|
// 98 STM32 handlers
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,ETH_IRQHandler,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
.word halt,halt,halt,halt,halt,halt,halt,halt
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global _reset
|
||||||
|
_reset:
|
||||||
|
ldr sp, =_estack
|
||||||
|
bl main
|
||||||
|
b .
|
||||||
|
|
||||||
|
halt: b .
|
||||||
|
pass: bx lr
|
||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,87 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file core_cmFunc.h
|
||||||
|
* @brief CMSIS Cortex-M Core Function Access Header File
|
||||||
|
* @version V4.30
|
||||||
|
* @date 20. October 2015
|
||||||
|
******************************************************************************/
|
||||||
|
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
- 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.
|
||||||
|
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined ( __ICCARM__ )
|
||||||
|
#pragma system_include /* treat file as system include file for MISRA check */
|
||||||
|
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
|
#pragma clang system_header /* treat file as system include file */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CORE_CMFUNC_H
|
||||||
|
#define __CORE_CMFUNC_H
|
||||||
|
|
||||||
|
|
||||||
|
/* ########################### Core Function Access ########################### */
|
||||||
|
/** \ingroup CMSIS_Core_FunctionInterface
|
||||||
|
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------ RealView Compiler -----------------*/
|
||||||
|
#if defined ( __CC_ARM )
|
||||||
|
#include "cmsis_armcc.h"
|
||||||
|
|
||||||
|
/*------------------ ARM Compiler V6 -------------------*/
|
||||||
|
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
|
#include "cmsis_armcc_V6.h"
|
||||||
|
|
||||||
|
/*------------------ GNU Compiler ----------------------*/
|
||||||
|
#elif defined ( __GNUC__ )
|
||||||
|
#include "cmsis_gcc.h"
|
||||||
|
|
||||||
|
/*------------------ ICC Compiler ----------------------*/
|
||||||
|
#elif defined ( __ICCARM__ )
|
||||||
|
#include <cmsis_iar.h>
|
||||||
|
|
||||||
|
/*------------------ TI CCS Compiler -------------------*/
|
||||||
|
#elif defined ( __TMS470__ )
|
||||||
|
#include <cmsis_ccs.h>
|
||||||
|
|
||||||
|
/*------------------ TASKING Compiler ------------------*/
|
||||||
|
#elif defined ( __TASKING__ )
|
||||||
|
/*
|
||||||
|
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||||
|
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||||
|
* Including the CMSIS ones.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------ COSMIC Compiler -------------------*/
|
||||||
|
#elif defined ( __CSMC__ )
|
||||||
|
#include <cmsis_csm.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*@} end of CMSIS_Core_RegAccFunctions */
|
||||||
|
|
||||||
|
#endif /* __CORE_CMFUNC_H */
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file core_cmInstr.h
|
||||||
|
* @brief CMSIS Cortex-M Core Instruction Access Header File
|
||||||
|
* @version V4.30
|
||||||
|
* @date 20. October 2015
|
||||||
|
******************************************************************************/
|
||||||
|
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
- 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.
|
||||||
|
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined ( __ICCARM__ )
|
||||||
|
#pragma system_include /* treat file as system include file for MISRA check */
|
||||||
|
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
|
#pragma clang system_header /* treat file as system include file */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CORE_CMINSTR_H
|
||||||
|
#define __CORE_CMINSTR_H
|
||||||
|
|
||||||
|
|
||||||
|
/* ########################## Core Instruction Access ######################### */
|
||||||
|
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||||
|
Access to dedicated instructions
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------ RealView Compiler -----------------*/
|
||||||
|
#if defined ( __CC_ARM )
|
||||||
|
#include "cmsis_armcc.h"
|
||||||
|
|
||||||
|
/*------------------ ARM Compiler V6 -------------------*/
|
||||||
|
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
|
#include "cmsis_armcc_V6.h"
|
||||||
|
|
||||||
|
/*------------------ GNU Compiler ----------------------*/
|
||||||
|
#elif defined ( __GNUC__ )
|
||||||
|
#include "cmsis_gcc.h"
|
||||||
|
|
||||||
|
/*------------------ ICC Compiler ----------------------*/
|
||||||
|
#elif defined ( __ICCARM__ )
|
||||||
|
#include <cmsis_iar.h>
|
||||||
|
|
||||||
|
/*------------------ TI CCS Compiler -------------------*/
|
||||||
|
#elif defined ( __TMS470__ )
|
||||||
|
#include <cmsis_ccs.h>
|
||||||
|
|
||||||
|
/*------------------ TASKING Compiler ------------------*/
|
||||||
|
#elif defined ( __TASKING__ )
|
||||||
|
/*
|
||||||
|
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||||
|
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||||
|
* Including the CMSIS ones.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------ COSMIC Compiler -------------------*/
|
||||||
|
#elif defined ( __CSMC__ )
|
||||||
|
#include <cmsis_csm.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
|
||||||
|
|
||||||
|
#endif /* __CORE_CMINSTR_H */
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file core_cmSimd.h
|
||||||
|
* @brief CMSIS Cortex-M SIMD Header File
|
||||||
|
* @version V4.30
|
||||||
|
* @date 20. October 2015
|
||||||
|
******************************************************************************/
|
||||||
|
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
- 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.
|
||||||
|
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined ( __ICCARM__ )
|
||||||
|
#pragma system_include /* treat file as system include file for MISRA check */
|
||||||
|
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
|
#pragma clang system_header /* treat file as system include file */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CORE_CMSIMD_H
|
||||||
|
#define __CORE_CMSIMD_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ################### Compiler specific Intrinsics ########################### */
|
||||||
|
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||||
|
Access to dedicated SIMD instructions
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------ RealView Compiler -----------------*/
|
||||||
|
#if defined ( __CC_ARM )
|
||||||
|
#include "cmsis_armcc.h"
|
||||||
|
|
||||||
|
/*------------------ ARM Compiler V6 -------------------*/
|
||||||
|
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||||
|
#include "cmsis_armcc_V6.h"
|
||||||
|
|
||||||
|
/*------------------ GNU Compiler ----------------------*/
|
||||||
|
#elif defined ( __GNUC__ )
|
||||||
|
#include "cmsis_gcc.h"
|
||||||
|
|
||||||
|
/*------------------ ICC Compiler ----------------------*/
|
||||||
|
#elif defined ( __ICCARM__ )
|
||||||
|
#include <cmsis_iar.h>
|
||||||
|
|
||||||
|
/*------------------ TI CCS Compiler -------------------*/
|
||||||
|
#elif defined ( __TMS470__ )
|
||||||
|
#include <cmsis_ccs.h>
|
||||||
|
|
||||||
|
/*------------------ TASKING Compiler ------------------*/
|
||||||
|
#elif defined ( __TASKING__ )
|
||||||
|
/*
|
||||||
|
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||||
|
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||||
|
* Including the CMSIS ones.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------ COSMIC Compiler -------------------*/
|
||||||
|
#elif defined ( __CSMC__ )
|
||||||
|
#include <cmsis_csm.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __CORE_CMSIMD_H */
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
// Copyright (c) 2018-2021 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
// https://www.st.com/resource/en/reference_manual/dm00124865-stm32f75xxx-and-stm32f74xxx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
|
||||||
|
// Memory map: 2.2.2
|
||||||
|
|
||||||
|
#include "stm32f746xx.h"
|
||||||
|
//#include "stm32f7xx_hal.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
#define BIT(x) ((uint32_t) 1 << (x))
|
||||||
|
#define PIN(bank, num) ((((bank) - 'A') << 8) | (num))
|
||||||
|
|
||||||
|
static inline void spin(uint32_t count) {
|
||||||
|
while (count--) asm("nop");
|
||||||
|
}
|
||||||
|
static inline GPIO_TypeDef *gpio_bank(uint16_t pin) {
|
||||||
|
return (GPIO_TypeDef *) (0x40020000 + 0x400 * (pin >> 8));
|
||||||
|
}
|
||||||
|
static inline void gpio_on(uint16_t pin) {
|
||||||
|
gpio_bank(pin)->ODR |= BIT(pin & 255);
|
||||||
|
}
|
||||||
|
static inline void gpio_off(uint16_t pin) {
|
||||||
|
gpio_bank(pin)->ODR &= ~BIT(pin & 255);
|
||||||
|
}
|
||||||
|
static inline void gpio_toggle(uint16_t pin) {
|
||||||
|
gpio_bank(pin)->ODR ^= BIT(pin & 255);
|
||||||
|
}
|
||||||
|
enum { GPIO_IN, GPIO_OUT, GPIO_AF, GPIO_ANALOG };
|
||||||
|
enum { GPIO_PP, GPIO_OD };
|
||||||
|
enum { GPIO_SPEED_LOW, GPIO_SPEED_MEDIUM, GPIO_SPEED_HIGH, GPIO_SPEED_INSANE };
|
||||||
|
enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN };
|
||||||
|
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
|
||||||
|
uint8_t speed, uint8_t pull, uint8_t af) {
|
||||||
|
GPIO_TypeDef *gpio = gpio_bank(pin);
|
||||||
|
uint8_t n = pin & 255;
|
||||||
|
gpio->MODER &= ~(3 << (n * 2));
|
||||||
|
gpio->MODER |= (mode << (n * 2));
|
||||||
|
gpio->OTYPER &= ~(1 << n);
|
||||||
|
gpio->OTYPER |= (type << n);
|
||||||
|
gpio->OSPEEDR &= ~(3 << (n * 2));
|
||||||
|
gpio->OSPEEDR |= (speed << (n * 2));
|
||||||
|
gpio->PUPDR &= ~(3 << (n * 2));
|
||||||
|
gpio->PUPDR |= (pull << (n * 2));
|
||||||
|
if (n < 8) {
|
||||||
|
gpio->AFR[0] &= 15 << (n * 4);
|
||||||
|
gpio->AFR[0] |= af << (n * 4);
|
||||||
|
} else {
|
||||||
|
gpio->AFR[1] &= 15 << (n * 4);
|
||||||
|
gpio->AFR[1] |= af << (n * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void init_clock(void) {
|
||||||
|
RCC->CR |= RCC_CR_HSEBYP | RCC_CR_HSEON; // Start HSE
|
||||||
|
while ((RCC->CR & RCC_CR_HSERDY) == 0) (void) 0;
|
||||||
|
|
||||||
|
#define PLL_M 8 // 8MHz HSE down-to 1MHz PLL input
|
||||||
|
#define PLL_N 432 // 432 MHz VCO output
|
||||||
|
#define PLL_P 2 // 216 MHz PLL output
|
||||||
|
#define PLL_Q 9 // 48 MHz (USB)
|
||||||
|
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) |
|
||||||
|
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
|
||||||
|
RCC->CR |= RCC_CR_PLLON; // Enable the main PLL
|
||||||
|
FLASH->ACR = FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_4WS;
|
||||||
|
|
||||||
|
// Configure AHB/APB prescalers
|
||||||
|
// AHB Prescaler = /1 -> 216 MHz
|
||||||
|
// APB1 Prescaler = /4 -> 54 MHz
|
||||||
|
// APB2 Prescaler = /2 -> 108 MHz
|
||||||
|
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||||
|
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
||||||
|
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
||||||
|
while ((RCC->CR & RCC_CR_PLLRDY) == 0) (void) 0;
|
||||||
|
|
||||||
|
RCC->CFGR &= ~RCC_CFGR_SW; // Select the main PLL
|
||||||
|
RCC->CFGR |= RCC_CFGR_SW_PLL; // as system clock source
|
||||||
|
while ((RCC->CFGR & RCC_CFGR_SWS) == 0) (void) 0;
|
||||||
|
|
||||||
|
// Ethernet clock
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_ETHMACEN;
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_ETHMACTXEN;
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_ETHMACRXEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define delay(ms) vTaskDelay(pdMS_TO_TICKS(ms))
|
||||||
|
|
||||||
|
#define LED1 PIN('B', 0) // On-board LED pin
|
||||||
|
#define LED2 PIN('B', 7) // On-board LED pin
|
||||||
|
#define LED3 PIN('B', 14) // On-board LED pin
|
||||||
|
|
||||||
|
static inline void led_toggle(void) {
|
||||||
|
gpio_toggle(LED2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void init_ram(void) {
|
||||||
|
extern uint32_t _sbss, _ebss;
|
||||||
|
extern uint32_t _sdata, _edata, _sidata;
|
||||||
|
memset(&_sbss, 0, ((char *) &_ebss - (char *) &_sbss));
|
||||||
|
memcpy(&_sdata, &_sidata, ((char *) &_edata - (char *) &_sdata));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void init_hardware(void) {
|
||||||
|
init_ram();
|
||||||
|
init_clock();
|
||||||
|
RCC->AHB1ENR |= BIT(0) | BIT(1) | BIT(2) | BIT(6); // Init GPIO banks A,B,C,G
|
||||||
|
gpio_init(LED1, GPIO_OUT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_NONE, 0);
|
||||||
|
gpio_init(LED2, GPIO_OUT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_NONE, 0);
|
||||||
|
gpio_init(LED3, GPIO_OUT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_NONE, 0);
|
||||||
|
gpio_on(LED2);
|
||||||
|
#if 0
|
||||||
|
uint16_t a1 = PIN('A', 1), a2 = PIN('A', 2), a7 = PIN('A', 7);
|
||||||
|
gpio_init(a1, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(a2, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(a7, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
|
||||||
|
uint16_t b13 = PIN('B', 13);
|
||||||
|
gpio_init(b13, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
|
||||||
|
uint16_t c1 = PIN('C', 1), c4 = PIN('C', 4), c5 = PIN('C', 5);
|
||||||
|
gpio_init(c1, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(c4, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(c5, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
|
||||||
|
uint16_t g2 = PIN('G', 2), g11 = PIN('G', 11), g13 = PIN('G', 13),
|
||||||
|
g14 = PIN('G', 14);
|
||||||
|
gpio_init(g2, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(g11, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(g13, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
gpio_init(g14, GPIO_AF, GPIO_PP, GPIO_SPEED_INSANE, GPIO_PULL_NONE, 11);
|
||||||
|
|
||||||
|
HAL_Init();
|
||||||
|
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
|
||||||
|
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
ENTRY(_reset);
|
||||||
|
MEMORY {
|
||||||
|
ram(rwx) : ORIGIN = 0x20000000, LENGTH = 307k
|
||||||
|
rom(rx) : ORIGIN = 0x08000000, LENGTH = 1024k
|
||||||
|
}
|
||||||
|
_estack = ORIGIN(ram) + LENGTH(ram); /* boot.s and init_heap() */
|
||||||
|
SECTIONS {
|
||||||
|
.vectortab : { KEEP(*(.vectortab)) } > rom
|
||||||
|
.text : { *(.text*) } > rom
|
||||||
|
.rodata : { *(.rodata*) } > rom
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
_sdata = .; /* for init_ram() */
|
||||||
|
*(.first_data)
|
||||||
|
*(.data SORT(.data.*))
|
||||||
|
_edata = .; /* for init_ram() */
|
||||||
|
} > ram AT > rom
|
||||||
|
_sidata = LOADADDR(.data);
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
_sbss = .; /* for init_ram() */
|
||||||
|
__bss_start__ = _sbss; /* for libc */
|
||||||
|
*(.bss SORT(.bss.*) COMMON)
|
||||||
|
_ebss = .; /* for init_ram() */
|
||||||
|
__bss_end__ = _ebss; /* for libc */
|
||||||
|
} > ram
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
end = .; /* for syscalls.c */
|
||||||
|
_end = .; /* for cmsis_gcc.h and init_ram() */
|
||||||
|
__end__ = .; /* for libc */
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
|
||||||
|
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||||
|
* not need to be guarded with a critical section. */
|
||||||
|
#define portTICK_TYPE_IS_ATOMIC 1
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
#define portYIELD() \
|
||||||
|
{ \
|
||||||
|
/* Set a PendSV to request a context switch. */ \
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||||
|
\
|
||||||
|
/* Barriers are normally not required but do ensure the code is completely \
|
||||||
|
* within the specified behaviour for the architecture. */ \
|
||||||
|
__asm volatile ( "dsb" ::: "memory" ); \
|
||||||
|
__asm volatile ( "isb" ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
|
||||||
|
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
* not necessary for to use this port. They are defined so the common demo files
|
||||||
|
* (which build with all the ports) will build. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specific optimisations. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||||
|
|
||||||
|
/* Generic helper function. */
|
||||||
|
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||||
|
{
|
||||||
|
uint8_t ucReturn;
|
||||||
|
|
||||||
|
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||||
|
|
||||||
|
return ucReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the configuration. */
|
||||||
|
#if ( configMAX_PRIORITIES > 32 )
|
||||||
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store/clear the ready priorities in a bit map. */
|
||||||
|
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||||
|
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
#define portINLINE __inline
|
||||||
|
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
|
||||||
|
|
||||||
|
if( ulCurrentInterrupt == 0 )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||||
|
{
|
||||||
|
uint32_t ulNewBASEPRI;
|
||||||
|
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" mov %0, %1 \n"\
|
||||||
|
" cpsid i \n"\
|
||||||
|
" msr basepri, %0 \n"\
|
||||||
|
" isb \n"\
|
||||||
|
" dsb \n"\
|
||||||
|
" cpsie i \n"\
|
||||||
|
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||||
|
{
|
||||||
|
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||||
|
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" mrs %0, basepri \n"\
|
||||||
|
" mov %1, %2 \n"\
|
||||||
|
" cpsid i \n"\
|
||||||
|
" msr basepri, %1 \n"\
|
||||||
|
" isb \n"\
|
||||||
|
" dsb \n"\
|
||||||
|
" cpsie i \n"\
|
||||||
|
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* This return will not be reached but is necessary to prevent compiler
|
||||||
|
* warnings. */
|
||||||
|
return ulOriginalBASEPRI;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,220 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file stm32f7xx.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief CMSIS STM32F7xx 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 STM32F7xx 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) 2016 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
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CMSIS
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup stm32f7xx
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __STM32F7xx_H
|
||||||
|
#define __STM32F7xx_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/** @addtogroup Library_configuration_section
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief STM32 Family
|
||||||
|
*/
|
||||||
|
#if !defined (STM32F7)
|
||||||
|
#define STM32F7
|
||||||
|
#endif /* STM32F7 */
|
||||||
|
|
||||||
|
/* Uncomment the line below according to the target STM32 device used in your
|
||||||
|
application
|
||||||
|
*/
|
||||||
|
#if !defined (STM32F756xx) && !defined (STM32F746xx) && !defined (STM32F745xx) && !defined (STM32F765xx) && \
|
||||||
|
!defined (STM32F767xx) && !defined (STM32F769xx) && !defined (STM32F777xx) && !defined (STM32F779xx) && \
|
||||||
|
!defined (STM32F722xx) && !defined (STM32F723xx) && !defined (STM32F732xx) && !defined (STM32F733xx) && \
|
||||||
|
!defined (STM32F730xx) && !defined (STM32F750xx)
|
||||||
|
|
||||||
|
/* #define STM32F756xx */ /*!< STM32F756VG, STM32F756ZG, STM32F756ZG, STM32F756IG, STM32F756BG,
|
||||||
|
STM32F756NG Devices */
|
||||||
|
/* #define STM32F746xx */ /*!< STM32F746VE, STM32F746VG, STM32F746ZE, STM32F746ZG, STM32F746IE, STM32F746IG,
|
||||||
|
STM32F746BE, STM32F746BG, STM32F746NE, STM32F746NG Devices */
|
||||||
|
/* #define STM32F745xx */ /*!< STM32F745VE, STM32F745VG, STM32F745ZG, STM32F745ZE, STM32F745IE, STM32F745IG Devices */
|
||||||
|
/* #define STM32F765xx */ /*!< STM32F765BI, STM32F765BG, STM32F765NI, STM32F765NG, STM32F765II, STM32F765IG,
|
||||||
|
STM32F765ZI, STM32F765ZG, STM32F765VI, STM32F765VG Devices */
|
||||||
|
/* #define STM32F767xx */ /*!< STM32F767BG, STM32F767BI, STM32F767IG, STM32F767II, STM32F767NG, STM32F767NI,
|
||||||
|
STM32F767VG, STM32F767VI, STM32F767ZG, STM32F767ZI Devices */
|
||||||
|
/* #define STM32F769xx */ /*!< STM32F769AG, STM32F769AI, STM32F769BG, STM32F769BI, STM32F769IG, STM32F769II,
|
||||||
|
STM32F769NG, STM32F769NI, STM32F768AI Devices */
|
||||||
|
/* #define STM32F777xx */ /*!< STM32F777VI, STM32F777ZI, STM32F777II, STM32F777BI, STM32F777NI Devices */
|
||||||
|
/* #define STM32F779xx */ /*!< STM32F779II, STM32F779BI, STM32F779NI, STM32F779AI, STM32F778AI Devices */
|
||||||
|
/* #define STM32F722xx */ /*!< STM32F722IE, STM32F722ZE, STM32F722VE, STM32F722RE, STM32F722IC, STM32F722ZC,
|
||||||
|
STM32F722VC, STM32F722RC Devices */
|
||||||
|
/* #define STM32F723xx */ /*!< STM32F723IE, STM32F723ZE, STM32F723VE, STM32F723IC, STM32F723ZC, STM32F723VC Devices */
|
||||||
|
/* #define STM32F732xx */ /*!< STM32F732IE, STM32F732ZE, STM32F732VE, STM32F732RE Devices */
|
||||||
|
/* #define STM32F733xx */ /*!< STM32F733IE, STM32F733ZE, STM32F733VE Devices */
|
||||||
|
/* #define STM32F730xx */ /*!< STM32F730R, STM32F730V, STM32F730Z, STM32F730I Devices */
|
||||||
|
/* #define STM32F750xx */ /*!< STM32F750V, STM32F750Z, STM32F750N Devices */
|
||||||
|
#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 V1.2.6
|
||||||
|
*/
|
||||||
|
#define __STM32F7_CMSIS_VERSION_MAIN (0x01) /*!< [31:24] main version */
|
||||||
|
#define __STM32F7_CMSIS_VERSION_SUB1 (0x02) /*!< [23:16] sub1 version */
|
||||||
|
#define __STM32F7_CMSIS_VERSION_SUB2 (0x06) /*!< [15:8] sub2 version */
|
||||||
|
#define __STM32F7_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */
|
||||||
|
#define __STM32F7_CMSIS_VERSION ((__STM32F7_CMSIS_VERSION_MAIN << 24)\
|
||||||
|
|(__STM32F7_CMSIS_VERSION_SUB1 << 16)\
|
||||||
|
|(__STM32F7_CMSIS_VERSION_SUB2 << 8 )\
|
||||||
|
|(__STM32F7_CMSIS_VERSION_RC))
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup Device_Included
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#if defined(STM32F722xx)
|
||||||
|
#include "stm32f722xx.h"
|
||||||
|
#elif defined(STM32F723xx)
|
||||||
|
#include "stm32f723xx.h"
|
||||||
|
#elif defined(STM32F732xx)
|
||||||
|
#include "stm32f732xx.h"
|
||||||
|
#elif defined(STM32F733xx)
|
||||||
|
#include "stm32f733xx.h"
|
||||||
|
#elif defined(STM32F756xx)
|
||||||
|
#include "stm32f756xx.h"
|
||||||
|
#elif defined(STM32F746xx)
|
||||||
|
#include "stm32f746xx.h"
|
||||||
|
#elif defined(STM32F745xx)
|
||||||
|
#include "stm32f745xx.h"
|
||||||
|
#elif defined(STM32F765xx)
|
||||||
|
#include "stm32f765xx.h"
|
||||||
|
#elif defined(STM32F767xx)
|
||||||
|
#include "stm32f767xx.h"
|
||||||
|
#elif defined(STM32F769xx)
|
||||||
|
#include "stm32f769xx.h"
|
||||||
|
#elif defined(STM32F777xx)
|
||||||
|
#include "stm32f777xx.h"
|
||||||
|
#elif defined(STM32F779xx)
|
||||||
|
#include "stm32f779xx.h"
|
||||||
|
#elif defined(STM32F730xx)
|
||||||
|
#include "stm32f730xx.h"
|
||||||
|
#elif defined(STM32F750xx)
|
||||||
|
#include "stm32f750xx.h"
|
||||||
|
#else
|
||||||
|
#error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup Exported_types
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RESET = 0U,
|
||||||
|
SET = !RESET
|
||||||
|
} FlagStatus, ITStatus;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DISABLE = 0U,
|
||||||
|
ENABLE = !DISABLE
|
||||||
|
} FunctionalState;
|
||||||
|
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SUCCESS = 0U,
|
||||||
|
ERROR = !SUCCESS
|
||||||
|
} ErrorStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup Exported_macro
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#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)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_HAL_DRIVER
|
||||||
|
#include "stm32f7xx_hal.h"
|
||||||
|
#endif /* USE_HAL_DRIVER */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __STM32F7xx_H */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file system_stm32f7xx.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @brief CMSIS Cortex-M7 Device System Source File for STM32F7xx devices.
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <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.
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CMSIS
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup stm32f7xx_system
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Define to prevent recursive inclusion
|
||||||
|
*/
|
||||||
|
#ifndef __SYSTEM_STM32F7XX_H
|
||||||
|
#define __SYSTEM_STM32F7XX_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_System_Includes
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_System_Exported_Variables
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/* The SystemCoreClock variable is updated in three ways:
|
||||||
|
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||||
|
2) by calling HAL API function HAL_RCC_GetSysClockFreq()
|
||||||
|
3) each time HAL_RCC_ClockConfig() is called to configure the system clock
|
||||||
|
frequency Note: If you use this function to configure the system clock; then
|
||||||
|
there is no need to call the 2 first functions listed above, since
|
||||||
|
SystemCoreClock variable is updated automatically.
|
||||||
|
*/
|
||||||
|
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||||
|
|
||||||
|
extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */
|
||||||
|
extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_System_Exported_Constants
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_System_Exported_Macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup STM32F7xx_System_Exported_Functions
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern void SystemInit(void);
|
||||||
|
extern void SystemCoreClockUpdate(void);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*__SYSTEM_STM32F7XX_H */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
@@ -32,8 +32,8 @@ static void broadcast_mjpeg_frame(struct mg_mgr *mgr) {
|
|||||||
size_t nfiles = sizeof(files) / sizeof(files[0]);
|
size_t nfiles = sizeof(files) / sizeof(files[0]);
|
||||||
static size_t i;
|
static size_t i;
|
||||||
const char *path = files[i++ % nfiles];
|
const char *path = files[i++ % nfiles];
|
||||||
size_t size = mg_file_size(path);
|
size_t size = 0;
|
||||||
char *data = mg_file_read(path); // Read next file
|
char *data = mg_file_read(path, &size); // Read next file
|
||||||
struct mg_connection *c;
|
struct mg_connection *c;
|
||||||
for (c = mgr->conns; c != NULL; c = c->next) {
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
if (c->label[0] != 'S') continue; // Skip non-stream connections
|
if (c->label[0] != 'S') continue; // Skip non-stream connections
|
||||||
|
|||||||
+764
-698
File diff suppressed because it is too large.
Load diff
+286
-168
@@ -14,8 +14,15 @@
|
|||||||
//
|
//
|
||||||
// Alternatively, you can license this software under a commercial
|
// Alternatively, you can license this software under a commercial
|
||||||
// license, as set out in <https://www.cesanta.com/license>.
|
// license, as set out in <https://www.cesanta.com/license>.
|
||||||
#pragma once
|
|
||||||
#define MG_VERSION "7.2"
|
#ifndef MONGOOSE_H
|
||||||
|
#define MONGOOSE_H
|
||||||
|
|
||||||
|
#define MG_VERSION "7.3"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define MG_ARCH_CUSTOM 0
|
#define MG_ARCH_CUSTOM 0
|
||||||
@@ -23,54 +30,20 @@
|
|||||||
#define MG_ARCH_WIN32 2
|
#define MG_ARCH_WIN32 2
|
||||||
#define MG_ARCH_ESP32 3
|
#define MG_ARCH_ESP32 3
|
||||||
#define MG_ARCH_ESP8266 4
|
#define MG_ARCH_ESP8266 4
|
||||||
#define MG_ARCH_CC3100 5
|
#define MG_ARCH_FREERTOS_TCP 5
|
||||||
#define MG_ARCH_CC3200 6
|
#define MG_ARCH_FREERTOS_LWIP 6
|
||||||
#define MG_ARCH_CC3220 7
|
|
||||||
#define MG_ARCH_MSP432 8
|
|
||||||
#define MG_ARCH_TM4C129 9
|
|
||||||
#define MG_ARCH_MBED 10
|
|
||||||
#define MG_ARCH_WINCE 11
|
|
||||||
#define MG_ARCH_NXP_LPC 12
|
|
||||||
#define MG_ARCH_NXP_KINETIS 13
|
|
||||||
#define MG_ARCH_NRF51 14
|
|
||||||
#define MG_ARCH_NRF52 15
|
|
||||||
#define MG_ARCH_PIC32 16
|
|
||||||
#define MG_ARCH_RS14100 17
|
|
||||||
#define MG_ARCH_STM32 18
|
|
||||||
#define MG_ARCH_FREERTOS 19
|
|
||||||
|
|
||||||
#if !defined(MG_ARCH)
|
#if !defined(MG_ARCH)
|
||||||
#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
#define MG_ARCH MG_ARCH_MSP432
|
|
||||||
#elif defined(cc3200) || defined(TARGET_IS_CC3200)
|
|
||||||
#define MG_ARCH MG_ARCH_CC3200
|
|
||||||
#elif defined(cc3220) || defined(TARGET_IS_CC3220)
|
|
||||||
#define MG_ARCH MG_ARCH_CC3220
|
|
||||||
#elif defined(__unix__) || defined(__APPLE__)
|
|
||||||
#define MG_ARCH MG_ARCH_UNIX
|
#define MG_ARCH MG_ARCH_UNIX
|
||||||
#elif defined(WINCE)
|
|
||||||
#define MG_ARCH MG_ARCH_WINCE
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#define MG_ARCH MG_ARCH_WIN32
|
#define MG_ARCH MG_ARCH_WIN32
|
||||||
#elif defined(__MBED__)
|
|
||||||
#define MG_ARCH MG_ARCH_MBED
|
|
||||||
#elif defined(__USE_LPCOPEN)
|
|
||||||
#define MG_ARCH MG_ARCH_NXP_LPC
|
|
||||||
#elif defined(FRDM_K64F) || defined(FREEDOM)
|
|
||||||
#define MG_ARCH MG_ARCH_NXP_KINETIS
|
|
||||||
#elif defined(PIC32)
|
|
||||||
#define MG_ARCH MG_ARCH_PIC32
|
|
||||||
#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
|
#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
|
||||||
#define MG_ARCH MG_ARCH_ESP8266
|
#define MG_ARCH MG_ARCH_ESP8266
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#define MG_ARCH MG_ARCH_ESP32
|
#define MG_ARCH MG_ARCH_ESP32
|
||||||
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
|
#elif defined(FREERTOS_IP_H)
|
||||||
defined(TARGET_IS_TM4C129_RA2)
|
#define MG_ARCH MG_ARCH_FREERTOS_TCP
|
||||||
#define MG_ARCH MG_ARCH_TM4C129
|
|
||||||
#elif defined(RS14100)
|
|
||||||
#define MG_ARCH MG_ARCH_RS14100
|
|
||||||
#elif defined(STM32)
|
|
||||||
#define MG_ARCH MG_ARCH_STM32
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MG_ARCH)
|
#if !defined(MG_ARCH)
|
||||||
@@ -78,23 +51,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif // !defined(MG_ARCH)
|
#endif // !defined(MG_ARCH)
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#if !defined(PRINTF_LIKE)
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||||||
|
#else
|
||||||
// Standard C headers
|
#define PRINTF_LIKE(f, a)
|
||||||
#include <ctype.h>
|
#endif
|
||||||
#include <errno.h>
|
#endif
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_CUSTOM
|
#if MG_ARCH == MG_ARCH_CUSTOM
|
||||||
#include <mongoose_custom.h>
|
#include <mongoose_custom.h>
|
||||||
@@ -106,20 +69,25 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(PRINTF_LIKE)
|
|
||||||
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
|
||||||
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
|
||||||
#else
|
|
||||||
#define PRINTF_LIKE(f, a)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_ESP32
|
#if MG_ARCH == MG_ARCH_ESP32
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
#define MG_INT64_FMT "%lld"
|
#define MG_INT64_FMT "%lld"
|
||||||
#ifndef MG_PATH_MAX
|
#ifndef MG_PATH_MAX
|
||||||
@@ -131,28 +99,102 @@
|
|||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_ESP8266
|
#if MG_ARCH == MG_ARCH_ESP8266
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <esp_system.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <esp_system.h>
|
||||||
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
#define MG_INT64_FMT "%lld"
|
#define MG_INT64_FMT "%lld"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||||||
#include <FreeRTOS.h>
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#else
|
||||||
|
typedef long suseconds_t;
|
||||||
|
struct timeval {
|
||||||
|
time_t tv_sec;
|
||||||
|
suseconds_t tv_usec;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_ENABLE_FS
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
|
||||||
#include <FreeRTOS_IP.h>
|
#include <lwip/sockets.h>
|
||||||
#include <FreeRTOS_Sockets.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#define MG_INT64_FMT "%lld"
|
#define MG_INT64_FMT "%lld"
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
|
|
||||||
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||||||
|
static inline void *mg_calloc(int cnt, size_t size) {
|
||||||
|
void *p = pvPortMalloc(cnt * size);
|
||||||
|
if (p != NULL) memset(p, 0, size);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#define calloc(a, b) mg_calloc((a), (b))
|
||||||
|
#define free(a) vPortFree(a)
|
||||||
|
#define malloc(a) pvPortMalloc(a)
|
||||||
|
|
||||||
|
#define gmtime_r(a, b) gmtime(a)
|
||||||
|
|
||||||
|
#endif // MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||||||
|
|
||||||
|
|
||||||
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if MG_ENABLE_FS
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <FreeRTOS_IP.h>
|
||||||
|
#include <FreeRTOS_Sockets.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
|
#define MG_INT64_FMT "%lld"
|
||||||
|
#define MG_DIRSEP '/'
|
||||||
|
|
||||||
|
// Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing
|
||||||
|
// with FreeRTOS_ prefix, is beyond me
|
||||||
#define IPPROTO_TCP FREERTOS_IPPROTO_TCP
|
#define IPPROTO_TCP FREERTOS_IPPROTO_TCP
|
||||||
#define IPPROTO_UDP FREERTOS_IPPROTO_UDP
|
#define IPPROTO_UDP FREERTOS_IPPROTO_UDP
|
||||||
#define AF_INET FREERTOS_AF_INET
|
#define AF_INET FREERTOS_AF_INET
|
||||||
@@ -163,9 +205,7 @@
|
|||||||
#define SOL_SOCKET 0
|
#define SOL_SOCKET 0
|
||||||
#define SO_REUSEADDR 0
|
#define SO_REUSEADDR 0
|
||||||
#define sockaddr_in freertos_sockaddr
|
#define sockaddr_in freertos_sockaddr
|
||||||
struct sockaddr {
|
#define sockaddr freertos_sockaddr
|
||||||
uint8_t sa_len, sa_family;
|
|
||||||
};
|
|
||||||
#define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
|
#define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
|
||||||
#define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
|
#define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
|
||||||
#define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
|
#define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
|
||||||
@@ -180,48 +220,72 @@ struct sockaddr {
|
|||||||
#define closesocket(x) FreeRTOS_closesocket(x)
|
#define closesocket(x) FreeRTOS_closesocket(x)
|
||||||
#define gethostbyname(x) FreeRTOS_gethostbyname(x)
|
#define gethostbyname(x) FreeRTOS_gethostbyname(x)
|
||||||
|
|
||||||
#include <ff_stdio.h>
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||||||
|
static inline void *mg_calloc(int cnt, size_t size) {
|
||||||
#undef FILE
|
void *p = pvPortMalloc(cnt * size);
|
||||||
#define FILE FF_FILE
|
if (p != NULL) memset(p, 0, size);
|
||||||
//#define SEEK_SET FF_SEEK_SET
|
return p;
|
||||||
//#define SEEK_END FF_SEEK_END
|
|
||||||
#define stat(a, b) ff_stat((a), (b))
|
|
||||||
#define fopen(a, b) ff_fopen((a), (b))
|
|
||||||
#define fclose(a) ff_fclose(a)
|
|
||||||
#define fread(a, b, c, d) ff_fread((a), (b), (c), (d))
|
|
||||||
#define fwrite(a, b, c, d) ff_fwrite((a), (b), (c), (d))
|
|
||||||
#define vfprintf ff_vfprintf
|
|
||||||
#define fprintf ff_fprintf
|
|
||||||
#define remove(a) ff_remove(a)
|
|
||||||
#define rename(a, b) ff_rename((a), (b), 1)
|
|
||||||
|
|
||||||
static inline int ff_vfprintf(FF_FILE *fp, const char *fmt, va_list ap) {
|
|
||||||
char *buf = NULL;
|
|
||||||
int n = mg_vasprintf(&buf, 0, fmt, ap);
|
|
||||||
if (buf != NULL) ff_fwrite(buf, 1, n, fp), free(buf);
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
#define calloc(a, b) mg_calloc((a), (b))
|
||||||
|
#define free(a) vPortFree(a)
|
||||||
|
#define malloc(a) pvPortMalloc(a)
|
||||||
|
|
||||||
|
#define gmtime_r(a, b) gmtime(a)
|
||||||
|
|
||||||
|
#if !defined(__GNUC__)
|
||||||
|
// copied from GCC on ARM; for some reason useconds are signed
|
||||||
|
typedef long suseconds_t;
|
||||||
|
struct timeval {
|
||||||
|
time_t tv_sec;
|
||||||
|
suseconds_t tv_usec;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EINPROGRESS
|
||||||
|
#define EINPROGRESS pdFREERTOS_ERRNO_EINPROGRESS
|
||||||
|
#endif
|
||||||
|
#ifndef EWOULDBLOCK
|
||||||
|
#define EWOULDBLOCK pdFREERTOS_ERRNO_EWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
#ifndef EAGAIN
|
||||||
|
#define EAGAIN pdFREERTOS_ERRNO_EAGAIN
|
||||||
|
#endif
|
||||||
|
#ifndef EINTR
|
||||||
|
#define EINTR pdFREERTOS_ERRNO_EINTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
|
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_UNIX
|
#if MG_ARCH == MG_ARCH_UNIX
|
||||||
|
|
||||||
#define _DARWIN_UNLIMITED_SELECT 1
|
#define _DARWIN_UNLIMITED_SELECT 1
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
#define MG_ENABLE_POSIX 1
|
#define MG_ENABLE_POSIX 1
|
||||||
#define MG_INT64_FMT "%" PRId64
|
#define MG_INT64_FMT "%" PRId64
|
||||||
@@ -231,6 +295,31 @@ static inline int ff_vfprintf(FF_FILE *fp, const char *fmt, va_list ap) {
|
|||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_WIN32
|
#if MG_ARCH == MG_ARCH_WIN32
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||||
#define __func__ ""
|
#define __func__ ""
|
||||||
typedef __int64 int64_t;
|
typedef __int64 int64_t;
|
||||||
@@ -258,6 +347,7 @@ typedef enum { false = 0, true = 1 } bool;
|
|||||||
#define strdup(x) _strdup(x)
|
#define strdup(x) _strdup(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned suseconds_t;
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#define MG_DIRSEP '\\'
|
#define MG_DIRSEP '\\'
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
@@ -270,6 +360,7 @@ typedef int socklen_t;
|
|||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
#endif
|
#endif
|
||||||
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
||||||
|
#define fopen(a, b) mg_fopen((a), (b))
|
||||||
#ifndef va_copy
|
#ifndef va_copy
|
||||||
#ifdef __va_copy
|
#ifdef __va_copy
|
||||||
#define va_copy __va_copy
|
#define va_copy __va_copy
|
||||||
@@ -283,16 +374,28 @@ typedef int socklen_t;
|
|||||||
|
|
||||||
#define MG_INT64_FMT "%I64d"
|
#define MG_INT64_FMT "%I64d"
|
||||||
|
|
||||||
|
static __inline FILE *mg_fopen(const char *path, const char *mode) {
|
||||||
|
wchar_t b1[PATH_MAX], b2[10];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
|
||||||
|
return _wfopen(b1, b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
|
||||||
|
static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
|
||||||
|
(void) tm;
|
||||||
|
return gmtime(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
|
||||||
|
(void) tm;
|
||||||
|
return localtime(t);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef MG_ENABLE_LWIP
|
#ifndef MG_ENABLE_SOCKET
|
||||||
#define MG_ENABLE_LWIP 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_ENABLE_LWIP
|
|
||||||
#define MG_ENABLE_SOCKET 0
|
|
||||||
#elif !defined(MG_ENABLE_SOCKET)
|
|
||||||
#define MG_ENABLE_SOCKET 1
|
#define MG_ENABLE_SOCKET 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -320,14 +423,15 @@ typedef int socklen_t;
|
|||||||
#define MG_ENABLE_LOG 1
|
#define MG_ENABLE_LOG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_MGOS
|
|
||||||
#define MG_ENABLE_MGOS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MG_ENABLE_MD5
|
#ifndef MG_ENABLE_MD5
|
||||||
#define MG_ENABLE_MD5 0
|
#define MG_ENABLE_MD5 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
|
||||||
|
#ifndef MG_ENABLE_WINSOCK
|
||||||
|
#define MG_ENABLE_WINSOCK 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_DIRECTORY_LISTING
|
#ifndef MG_ENABLE_DIRECTORY_LISTING
|
||||||
#define MG_ENABLE_DIRECTORY_LISTING 0
|
#define MG_ENABLE_DIRECTORY_LISTING 0
|
||||||
#endif
|
#endif
|
||||||
@@ -366,6 +470,9 @@ struct mg_str {
|
|||||||
#define MG_NULL_STR \
|
#define MG_NULL_STR \
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
|
|
||||||
|
// Using macro to avoid shadowing C++ struct constructor, see #1298
|
||||||
|
#define mg_str(s) mg_str_s(s)
|
||||||
|
|
||||||
struct mg_str mg_str(const char *s);
|
struct mg_str mg_str(const char *s);
|
||||||
struct mg_str mg_str_n(const char *s, size_t n);
|
struct mg_str mg_str_n(const char *s, size_t n);
|
||||||
int mg_lower(const char *s);
|
int mg_lower(const char *s);
|
||||||
@@ -382,9 +489,6 @@ const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MG_ENABLE_MGOS
|
|
||||||
#include <common/cs_dbg.h>
|
|
||||||
#else
|
|
||||||
#if MG_ENABLE_LOG
|
#if MG_ENABLE_LOG
|
||||||
#define LOG(level, args) \
|
#define LOG(level, args) \
|
||||||
do { \
|
do { \
|
||||||
@@ -394,27 +498,28 @@ enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG };
|
|||||||
bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
|
bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
|
||||||
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||||
void mg_log_set(const char *spec);
|
void mg_log_set(const char *spec);
|
||||||
void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param);
|
void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
|
||||||
#else
|
#else
|
||||||
#define LOG(level, args)
|
#define LOG(level, args) (void) 0
|
||||||
#endif
|
#define mg_log_set(x) (void) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct mg_timer {
|
struct mg_timer {
|
||||||
int period_ms; // Timer period in milliseconds
|
unsigned long period_ms; // Timer period in milliseconds
|
||||||
int flags; // Possible flags values below
|
unsigned flags; // Possible flags values below
|
||||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||||
void (*fn)(void *); // Function to call
|
void (*fn)(void *); // Function to call
|
||||||
void *arg; // Function agrument
|
void *arg; // Function argument
|
||||||
unsigned long expire; // Expiration timestamp in milliseconds
|
unsigned long expire; // Expiration timestamp in milliseconds
|
||||||
struct mg_timer *next; // Linkage in g_timers list
|
struct mg_timer *next; // Linkage in g_timers list
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct mg_timer *g_timers; // Global list of timers
|
extern struct mg_timer *g_timers; // Global list of timers
|
||||||
|
|
||||||
void mg_timer_init(struct mg_timer *, int ms, int, void (*fn)(void *), void *);
|
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
||||||
|
void (*fn)(void *), void *);
|
||||||
void mg_timer_free(struct mg_timer *);
|
void mg_timer_free(struct mg_timer *);
|
||||||
void mg_timer_poll(unsigned long uptime_ms);
|
void mg_timer_poll(unsigned long uptime_ms);
|
||||||
|
|
||||||
@@ -422,20 +527,33 @@ void mg_timer_poll(unsigned long uptime_ms);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *mg_file_read(const char *path);
|
// WEAK symbol makes it possible to define a "default" function implementation,
|
||||||
|
// which could be overridden by the user who can define a function with the
|
||||||
|
// same name without linking conflict
|
||||||
|
#if !defined(WEAK)
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__) || \
|
||||||
|
defined(__TI_COMPILER_VERSION__)) && \
|
||||||
|
!defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
#define WEAK __attribute__((weak))
|
||||||
|
#else
|
||||||
|
#define WEAK
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *mg_file_read(const char *path, size_t *size);
|
||||||
int64_t mg_file_size(const char *path);
|
int64_t mg_file_size(const char *path);
|
||||||
bool mg_file_write(const char *path, const void *buf, size_t len);
|
bool mg_file_write(const char *path, const void *buf, size_t len);
|
||||||
bool mg_file_printf(const char *path, const char *fmt, ...);
|
bool mg_file_printf(const char *path, const char *fmt, ...);
|
||||||
void mg_random(void *buf, size_t len);
|
void mg_random(void *buf, size_t len) WEAK;
|
||||||
bool mg_globmatch(const char *pattern, int plen, const char *s, int n);
|
bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
|
||||||
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||||
uint16_t mg_ntohs(uint16_t net);
|
uint16_t mg_ntohs(uint16_t net);
|
||||||
uint32_t mg_ntohl(uint32_t net);
|
uint32_t mg_ntohl(uint32_t net);
|
||||||
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
||||||
char *mg_hexdump(const void *buf, size_t len);
|
char *mg_hexdump(const void *buf, size_t len);
|
||||||
char *mg_hex(const void *buf, int len, char *dst);
|
char *mg_hex(const void *buf, size_t len, char *dst);
|
||||||
void mg_unhex(const char *buf, int len, unsigned char *to);
|
void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||||||
unsigned long mg_unhexn(const char *s, int len);
|
unsigned long mg_unhexn(const char *s, size_t len);
|
||||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||||
int64_t mg_to64(struct mg_str str);
|
int64_t mg_to64(struct mg_str str);
|
||||||
@@ -450,26 +568,11 @@ typedef struct _stati64 mg_stat_t;
|
|||||||
typedef struct stat mg_stat_t;
|
typedef struct stat mg_stat_t;
|
||||||
#endif
|
#endif
|
||||||
int mg_stat(const char *path, mg_stat_t *);
|
int mg_stat(const char *path, mg_stat_t *);
|
||||||
FILE *mg_fopen(const char *fp, const char *mode);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define mg_htons(x) mg_ntohs(x)
|
#define mg_htons(x) mg_ntohs(x)
|
||||||
#define mg_htonl(x) mg_ntohl(x)
|
#define mg_htonl(x) mg_ntohl(x)
|
||||||
|
|
||||||
#define MG_SWAP16(x) ((((x) >> 8) & 255) | ((x & 255) << 8))
|
|
||||||
#define MG_SWAP32(x) \
|
|
||||||
(((x) >> 24) | (((x) &0xff0000) >> 8) | (((x) &0xff00) << 8) | ((x) << 24))
|
|
||||||
|
|
||||||
#if !defined(WEAK)
|
|
||||||
#if (defined(__GNUC__) || defined(__clang__) || \
|
|
||||||
defined(__TI_COMPILER_VERSION__)) && \
|
|
||||||
!defined(_WIN32) && !defined(__CYGWIN__)
|
|
||||||
#define WEAK __attribute__((weak))
|
|
||||||
#else
|
|
||||||
#define WEAK
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Expands to a string representation of its argument: e.g.
|
// Expands to a string representation of its argument: e.g.
|
||||||
// MG_STRINGIFY_LITERAL(5) expands to "5"
|
// MG_STRINGIFY_LITERAL(5) expands to "5"
|
||||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||||
@@ -477,7 +580,12 @@ FILE *mg_fopen(const char *fp, const char *mode);
|
|||||||
#else
|
#else
|
||||||
#define MG_STRINGIFY_LITERAL(x) #x
|
#define MG_STRINGIFY_LITERAL(x) #x
|
||||||
#endif
|
#endif
|
||||||
|
// Expands to a string representation of its argument, which can be a macro:
|
||||||
|
// #define FOO 123
|
||||||
|
// MG_STRINGIFY_MACRO(FOO) // Expands to 123
|
||||||
|
#define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
|
||||||
|
|
||||||
|
// Linked list management macros
|
||||||
#define LIST_ADD_HEAD(type_, head_, elem_) \
|
#define LIST_ADD_HEAD(type_, head_, elem_) \
|
||||||
do { \
|
do { \
|
||||||
(elem_)->next = (*head_); \
|
(elem_)->next = (*head_); \
|
||||||
@@ -498,11 +606,6 @@ FILE *mg_fopen(const char *fp, const char *mode);
|
|||||||
*h = (elem_)->next; \
|
*h = (elem_)->next; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Expands to a string representation of its argument, which can be a macro:
|
|
||||||
// #define FOO 123
|
|
||||||
// MG_STRINGIFY_MACRO(FOO) // Expands to 123
|
|
||||||
#define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned short mg_url_port(const char *url);
|
unsigned short mg_url_port(const char *url);
|
||||||
@@ -574,7 +677,7 @@ enum {
|
|||||||
MG_EV_CONNECT, // Connection established NULL
|
MG_EV_CONNECT, // Connection established NULL
|
||||||
MG_EV_ACCEPT, // Connection accepted NULL
|
MG_EV_ACCEPT, // Connection accepted NULL
|
||||||
MG_EV_READ, // Data received from socket struct mg_str *
|
MG_EV_READ, // Data received from socket struct mg_str *
|
||||||
MG_EV_WRITE, // Data written to socket int *num_bytes_written
|
MG_EV_WRITE, // Data written to socket long *bytes_written
|
||||||
MG_EV_CLOSE, // Connection closed NULL
|
MG_EV_CLOSE, // Connection closed NULL
|
||||||
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
|
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
|
||||||
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
|
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
|
||||||
@@ -613,7 +716,7 @@ struct mg_mgr {
|
|||||||
int dnstimeout; // DNS resolve timeout in milliseconds
|
int dnstimeout; // DNS resolve timeout in milliseconds
|
||||||
unsigned long nextid; // Next connection ID
|
unsigned long nextid; // Next connection ID
|
||||||
void *userdata; // Arbitrary user data pointer
|
void *userdata; // Arbitrary user data pointer
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
SocketSet_t ss; // NOTE(lsm): referenced from socket struct
|
SocketSet_t ss; // NOTE(lsm): referenced from socket struct
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -621,13 +724,13 @@ struct mg_mgr {
|
|||||||
struct mg_connection {
|
struct mg_connection {
|
||||||
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
||||||
struct mg_mgr *mgr; // Our container
|
struct mg_mgr *mgr; // Our container
|
||||||
struct mg_addr peer; // Remote peer address
|
struct mg_addr peer; // Remote address. For listeners, local address
|
||||||
void *fd; // Connected socket, or LWIP data
|
void *fd; // Connected socket, or LWIP data
|
||||||
unsigned long id; // Auto-incrementing unique connection ID
|
unsigned long id; // Auto-incrementing unique connection ID
|
||||||
struct mg_iobuf recv; // Incoming data
|
struct mg_iobuf recv; // Incoming data
|
||||||
struct mg_iobuf send; // Outgoing data
|
struct mg_iobuf send; // Outgoing data
|
||||||
mg_event_handler_t fn; // User-specified event handler function
|
mg_event_handler_t fn; // User-specified event handler function
|
||||||
void *fn_data; // User-speficied function parameter
|
void *fn_data; // User-specified function parameter
|
||||||
mg_event_handler_t pfn; // Protocol-specific handler function
|
mg_event_handler_t pfn; // Protocol-specific handler function
|
||||||
void *pfn_data; // Protocol-specific function parameter
|
void *pfn_data; // Protocol-specific function parameter
|
||||||
char label[50]; // Arbitrary label
|
char label[50]; // Arbitrary label
|
||||||
@@ -635,7 +738,7 @@ struct mg_connection {
|
|||||||
unsigned is_listening : 1; // Listening connection
|
unsigned is_listening : 1; // Listening connection
|
||||||
unsigned is_client : 1; // Outbound (client) connection
|
unsigned is_client : 1; // Outbound (client) connection
|
||||||
unsigned is_accepted : 1; // Accepted (server) connection
|
unsigned is_accepted : 1; // Accepted (server) connection
|
||||||
unsigned is_resolving : 1; // Non-blocking DNS resolv is in progress
|
unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
|
||||||
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
||||||
unsigned is_tls : 1; // TLS-enabled connection
|
unsigned is_tls : 1; // TLS-enabled connection
|
||||||
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
||||||
@@ -656,7 +759,7 @@ struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
|
|||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
int mg_send(struct mg_connection *, const void *, size_t);
|
bool mg_send(struct mg_connection *, const void *, size_t);
|
||||||
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||||
char *mg_straddr(struct mg_connection *, char *, size_t);
|
char *mg_straddr(struct mg_connection *, char *, size_t);
|
||||||
@@ -688,8 +791,16 @@ struct mg_http_message {
|
|||||||
|
|
||||||
// Parameter for mg_http_serve_dir()
|
// Parameter for mg_http_serve_dir()
|
||||||
struct mg_http_serve_opts {
|
struct mg_http_serve_opts {
|
||||||
const char *root_dir; // Web root directory, must be non-NULL
|
const char *root_dir; // Web root directory, must be non-NULL
|
||||||
const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml
|
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
|
||||||
|
const char *extra_headers; // Extra HTTP headers to add in responses
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameter for mg_http_next_multipart
|
||||||
|
struct mg_http_part {
|
||||||
|
struct mg_str name; // Form field name
|
||||||
|
struct mg_str filename; // Filename for file uploads
|
||||||
|
struct mg_str body; // Part contents
|
||||||
};
|
};
|
||||||
|
|
||||||
int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
|
int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
|
||||||
@@ -709,14 +820,16 @@ void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
|
|||||||
const char *body_fmt, ...);
|
const char *body_fmt, ...);
|
||||||
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
||||||
void mg_http_event_handler(struct mg_connection *c, int ev);
|
void mg_http_event_handler(struct mg_connection *c, int ev);
|
||||||
int mg_http_get_var(const struct mg_str *, const char *name, char *, int);
|
int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
|
||||||
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
||||||
int mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
||||||
void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int);
|
void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
|
||||||
bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
|
bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
|
||||||
int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
|
int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
|
||||||
const char *dir);
|
const char *dir);
|
||||||
void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
||||||
|
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
|
||||||
|
size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
|
||||||
|
|
||||||
|
|
||||||
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
||||||
@@ -732,11 +845,11 @@ struct mg_tls_opts {
|
|||||||
struct mg_str srvname; // If not empty, enables server name verification
|
struct mg_str srvname; // If not empty, enables server name verification
|
||||||
};
|
};
|
||||||
|
|
||||||
int mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
|
void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
|
||||||
int mg_tls_free(struct mg_connection *);
|
void mg_tls_free(struct mg_connection *);
|
||||||
int mg_tls_send(struct mg_connection *, const void *buf, size_t len, int *fail);
|
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
|
||||||
int mg_tls_recv(struct mg_connection *, void *buf, size_t len, int *fail);
|
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
|
||||||
int mg_tls_handshake(struct mg_connection *);
|
void mg_tls_handshake(struct mg_connection *);
|
||||||
|
|
||||||
|
|
||||||
#define WEBSOCKET_OP_CONTINUE 0
|
#define WEBSOCKET_OP_CONTINUE 0
|
||||||
@@ -805,9 +918,9 @@ struct mg_mqtt_opts {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mg_mqtt_message {
|
struct mg_mqtt_message {
|
||||||
struct mg_str topic; // Parsed topic
|
struct mg_str topic; // Parsed topic
|
||||||
struct mg_str data; // Parsed message
|
struct mg_str data; // Parsed message
|
||||||
struct mg_str dgram; // Whole MQTT datagram, including headers
|
struct mg_str dgram; // Whole MQTT datagram, including headers
|
||||||
uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
|
uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
|
||||||
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
|
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
|
||||||
uint8_t qos; // Quality of service
|
uint8_t qos; // Quality of service
|
||||||
@@ -819,16 +932,16 @@ struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url,
|
|||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
void mg_mqtt_pub(struct mg_connection *, struct mg_str *topic,
|
void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
|
||||||
struct mg_str *data);
|
struct mg_str *data, int qos, bool retain);
|
||||||
void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic);
|
void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic, int qos);
|
||||||
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
|
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
|
||||||
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
|
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||||
uint8_t *qos, int pos);
|
uint8_t *qos, size_t pos);
|
||||||
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||||
int pos);
|
size_t pos);
|
||||||
void mg_mqtt_ping(struct mg_connection *);
|
void mg_mqtt_ping(struct mg_connection *);
|
||||||
void mg_mqtt_pong(struct mg_connection *);
|
void mg_mqtt_pong(struct mg_connection *);
|
||||||
void mg_mqtt_disconnect(struct mg_connection *);
|
void mg_mqtt_disconnect(struct mg_connection *);
|
||||||
@@ -871,3 +984,8 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
|||||||
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
||||||
bool is_question, struct mg_dns_rr *);
|
bool is_question, struct mg_dns_rr *);
|
||||||
size_t mg_dns_decode_name(const uint8_t *, size_t, size_t, char *, size_t);
|
size_t mg_dns_decode_name(const uint8_t *, size_t, size_t, char *, size_t);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // MONGOOSE_H
|
||||||
+16
-67
@@ -5,54 +5,20 @@
|
|||||||
#define MG_ARCH_WIN32 2
|
#define MG_ARCH_WIN32 2
|
||||||
#define MG_ARCH_ESP32 3
|
#define MG_ARCH_ESP32 3
|
||||||
#define MG_ARCH_ESP8266 4
|
#define MG_ARCH_ESP8266 4
|
||||||
#define MG_ARCH_CC3100 5
|
#define MG_ARCH_FREERTOS_TCP 5
|
||||||
#define MG_ARCH_CC3200 6
|
#define MG_ARCH_FREERTOS_LWIP 6
|
||||||
#define MG_ARCH_CC3220 7
|
|
||||||
#define MG_ARCH_MSP432 8
|
|
||||||
#define MG_ARCH_TM4C129 9
|
|
||||||
#define MG_ARCH_MBED 10
|
|
||||||
#define MG_ARCH_WINCE 11
|
|
||||||
#define MG_ARCH_NXP_LPC 12
|
|
||||||
#define MG_ARCH_NXP_KINETIS 13
|
|
||||||
#define MG_ARCH_NRF51 14
|
|
||||||
#define MG_ARCH_NRF52 15
|
|
||||||
#define MG_ARCH_PIC32 16
|
|
||||||
#define MG_ARCH_RS14100 17
|
|
||||||
#define MG_ARCH_STM32 18
|
|
||||||
#define MG_ARCH_FREERTOS 19
|
|
||||||
|
|
||||||
#if !defined(MG_ARCH)
|
#if !defined(MG_ARCH)
|
||||||
#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
#define MG_ARCH MG_ARCH_MSP432
|
|
||||||
#elif defined(cc3200) || defined(TARGET_IS_CC3200)
|
|
||||||
#define MG_ARCH MG_ARCH_CC3200
|
|
||||||
#elif defined(cc3220) || defined(TARGET_IS_CC3220)
|
|
||||||
#define MG_ARCH MG_ARCH_CC3220
|
|
||||||
#elif defined(__unix__) || defined(__APPLE__)
|
|
||||||
#define MG_ARCH MG_ARCH_UNIX
|
#define MG_ARCH MG_ARCH_UNIX
|
||||||
#elif defined(WINCE)
|
|
||||||
#define MG_ARCH MG_ARCH_WINCE
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#define MG_ARCH MG_ARCH_WIN32
|
#define MG_ARCH MG_ARCH_WIN32
|
||||||
#elif defined(__MBED__)
|
|
||||||
#define MG_ARCH MG_ARCH_MBED
|
|
||||||
#elif defined(__USE_LPCOPEN)
|
|
||||||
#define MG_ARCH MG_ARCH_NXP_LPC
|
|
||||||
#elif defined(FRDM_K64F) || defined(FREEDOM)
|
|
||||||
#define MG_ARCH MG_ARCH_NXP_KINETIS
|
|
||||||
#elif defined(PIC32)
|
|
||||||
#define MG_ARCH MG_ARCH_PIC32
|
|
||||||
#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
|
#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
|
||||||
#define MG_ARCH MG_ARCH_ESP8266
|
#define MG_ARCH MG_ARCH_ESP8266
|
||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#define MG_ARCH MG_ARCH_ESP32
|
#define MG_ARCH MG_ARCH_ESP32
|
||||||
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
|
#elif defined(FREERTOS_IP_H)
|
||||||
defined(TARGET_IS_TM4C129_RA2)
|
#define MG_ARCH MG_ARCH_FREERTOS_TCP
|
||||||
#define MG_ARCH MG_ARCH_TM4C129
|
|
||||||
#elif defined(RS14100)
|
|
||||||
#define MG_ARCH MG_ARCH_RS14100
|
|
||||||
#elif defined(STM32)
|
|
||||||
#define MG_ARCH MG_ARCH_STM32
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MG_ARCH)
|
#if !defined(MG_ARCH)
|
||||||
@@ -60,34 +26,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif // !defined(MG_ARCH)
|
#endif // !defined(MG_ARCH)
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
|
||||||
|
|
||||||
// Standard C headers
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_CUSTOM
|
|
||||||
#include <mongoose_custom.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arch_esp32.h"
|
|
||||||
#include "arch_esp8266.h"
|
|
||||||
#include "arch_freertos.h"
|
|
||||||
#include "arch_unix.h"
|
|
||||||
#include "arch_win32.h"
|
|
||||||
|
|
||||||
#if !defined(PRINTF_LIKE)
|
#if !defined(PRINTF_LIKE)
|
||||||
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||||||
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||||||
@@ -95,3 +33,14 @@
|
|||||||
#define PRINTF_LIKE(f, a)
|
#define PRINTF_LIKE(f, a)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MG_ARCH == MG_ARCH_CUSTOM
|
||||||
|
#include <mongoose_custom.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "arch_esp32.h"
|
||||||
|
#include "arch_esp8266.h"
|
||||||
|
#include "arch_freertos_lwip.h"
|
||||||
|
#include "arch_freertos_tcp.h"
|
||||||
|
#include "arch_unix.h"
|
||||||
|
#include "arch_win32.h"
|
||||||
@@ -2,9 +2,21 @@
|
|||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_ESP32
|
#if MG_ARCH == MG_ARCH_ESP32
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
#define MG_INT64_FMT "%lld"
|
#define MG_INT64_FMT "%lld"
|
||||||
#ifndef MG_PATH_MAX
|
#ifndef MG_PATH_MAX
|
||||||
|
|||||||
+15
-1
@@ -2,11 +2,25 @@
|
|||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_ESP8266
|
#if MG_ARCH == MG_ARCH_ESP8266
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <esp_system.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <esp_system.h>
|
||||||
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
#define MG_INT64_FMT "%lld"
|
#define MG_INT64_FMT "%lld"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#else
|
||||||
|
typedef long suseconds_t;
|
||||||
|
struct timeval {
|
||||||
|
time_t tv_sec;
|
||||||
|
suseconds_t tv_usec;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_ENABLE_FS
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
|
#include <lwip/sockets.h>
|
||||||
|
|
||||||
|
#define MG_INT64_FMT "%lld"
|
||||||
|
#define MG_DIRSEP '/'
|
||||||
|
|
||||||
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||||||
|
static inline void *mg_calloc(int cnt, size_t size) {
|
||||||
|
void *p = pvPortMalloc(cnt * size);
|
||||||
|
if (p != NULL) memset(p, 0, size);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#define calloc(a, b) mg_calloc((a), (b))
|
||||||
|
#define free(a) vPortFree(a)
|
||||||
|
#define malloc(a) pvPortMalloc(a)
|
||||||
|
|
||||||
|
#define gmtime_r(a, b) gmtime(a)
|
||||||
|
|
||||||
|
#endif // MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||||||
@@ -1,16 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if MG_ENABLE_FS
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
|
|
||||||
#include <task.h>
|
|
||||||
|
|
||||||
#include <FreeRTOS_IP.h>
|
#include <FreeRTOS_IP.h>
|
||||||
#include <FreeRTOS_Sockets.h>
|
#include <FreeRTOS_Sockets.h>
|
||||||
#include <stdbool.h>
|
#include <task.h>
|
||||||
|
|
||||||
#define MG_INT64_FMT "%lld"
|
#define MG_INT64_FMT "%lld"
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
|
|
||||||
|
// Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing
|
||||||
|
// with FreeRTOS_ prefix, is beyond me
|
||||||
#define IPPROTO_TCP FREERTOS_IPPROTO_TCP
|
#define IPPROTO_TCP FREERTOS_IPPROTO_TCP
|
||||||
#define IPPROTO_UDP FREERTOS_IPPROTO_UDP
|
#define IPPROTO_UDP FREERTOS_IPPROTO_UDP
|
||||||
#define AF_INET FREERTOS_AF_INET
|
#define AF_INET FREERTOS_AF_INET
|
||||||
@@ -21,9 +37,7 @@
|
|||||||
#define SOL_SOCKET 0
|
#define SOL_SOCKET 0
|
||||||
#define SO_REUSEADDR 0
|
#define SO_REUSEADDR 0
|
||||||
#define sockaddr_in freertos_sockaddr
|
#define sockaddr_in freertos_sockaddr
|
||||||
struct sockaddr {
|
#define sockaddr freertos_sockaddr
|
||||||
uint8_t sa_len, sa_family;
|
|
||||||
};
|
|
||||||
#define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
|
#define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
|
||||||
#define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
|
#define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
|
||||||
#define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
|
#define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
|
||||||
@@ -38,27 +52,38 @@ struct sockaddr {
|
|||||||
#define closesocket(x) FreeRTOS_closesocket(x)
|
#define closesocket(x) FreeRTOS_closesocket(x)
|
||||||
#define gethostbyname(x) FreeRTOS_gethostbyname(x)
|
#define gethostbyname(x) FreeRTOS_gethostbyname(x)
|
||||||
|
|
||||||
#include <ff_stdio.h>
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||||||
|
static inline void *mg_calloc(int cnt, size_t size) {
|
||||||
#undef FILE
|
void *p = pvPortMalloc(cnt * size);
|
||||||
#define FILE FF_FILE
|
if (p != NULL) memset(p, 0, size);
|
||||||
//#define SEEK_SET FF_SEEK_SET
|
return p;
|
||||||
//#define SEEK_END FF_SEEK_END
|
|
||||||
#define stat(a, b) ff_stat((a), (b))
|
|
||||||
#define fopen(a, b) ff_fopen((a), (b))
|
|
||||||
#define fclose(a) ff_fclose(a)
|
|
||||||
#define fread(a, b, c, d) ff_fread((a), (b), (c), (d))
|
|
||||||
#define fwrite(a, b, c, d) ff_fwrite((a), (b), (c), (d))
|
|
||||||
#define vfprintf ff_vfprintf
|
|
||||||
#define fprintf ff_fprintf
|
|
||||||
#define remove(a) ff_remove(a)
|
|
||||||
#define rename(a, b) ff_rename((a), (b), 1)
|
|
||||||
|
|
||||||
static inline int ff_vfprintf(FF_FILE *fp, const char *fmt, va_list ap) {
|
|
||||||
char *buf = NULL;
|
|
||||||
int n = mg_vasprintf(&buf, 0, fmt, ap);
|
|
||||||
if (buf != NULL) ff_fwrite(buf, 1, n, fp), free(buf);
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
#define calloc(a, b) mg_calloc((a), (b))
|
||||||
|
#define free(a) vPortFree(a)
|
||||||
|
#define malloc(a) pvPortMalloc(a)
|
||||||
|
|
||||||
|
#define gmtime_r(a, b) gmtime(a)
|
||||||
|
|
||||||
|
#if !defined(__GNUC__)
|
||||||
|
// copied from GCC on ARM; for some reason useconds are signed
|
||||||
|
typedef long suseconds_t;
|
||||||
|
struct timeval {
|
||||||
|
time_t tv_sec;
|
||||||
|
suseconds_t tv_usec;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EINPROGRESS
|
||||||
|
#define EINPROGRESS pdFREERTOS_ERRNO_EINPROGRESS
|
||||||
|
#endif
|
||||||
|
#ifndef EWOULDBLOCK
|
||||||
|
#define EWOULDBLOCK pdFREERTOS_ERRNO_EWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
#ifndef EAGAIN
|
||||||
|
#define EAGAIN pdFREERTOS_ERRNO_EAGAIN
|
||||||
|
#endif
|
||||||
|
#ifndef EINTR
|
||||||
|
#define EINTR pdFREERTOS_ERRNO_EINTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
@@ -5,17 +5,30 @@
|
|||||||
#define _DARWIN_UNLIMITED_SELECT 1
|
#define _DARWIN_UNLIMITED_SELECT 1
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define MG_DIRSEP '/'
|
#define MG_DIRSEP '/'
|
||||||
#define MG_ENABLE_POSIX 1
|
#define MG_ENABLE_POSIX 1
|
||||||
#define MG_INT64_FMT "%" PRId64
|
#define MG_INT64_FMT "%" PRId64
|
||||||
|
|||||||
@@ -2,6 +2,31 @@
|
|||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_WIN32
|
#if MG_ARCH == MG_ARCH_WIN32
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||||
#define __func__ ""
|
#define __func__ ""
|
||||||
typedef __int64 int64_t;
|
typedef __int64 int64_t;
|
||||||
@@ -29,6 +54,7 @@ typedef enum { false = 0, true = 1 } bool;
|
|||||||
#define strdup(x) _strdup(x)
|
#define strdup(x) _strdup(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned suseconds_t;
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#define MG_DIRSEP '\\'
|
#define MG_DIRSEP '\\'
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
@@ -41,6 +67,7 @@ typedef int socklen_t;
|
|||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
#endif
|
#endif
|
||||||
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
||||||
|
#define fopen(a, b) mg_fopen((a), (b))
|
||||||
#ifndef va_copy
|
#ifndef va_copy
|
||||||
#ifdef __va_copy
|
#ifdef __va_copy
|
||||||
#define va_copy __va_copy
|
#define va_copy __va_copy
|
||||||
@@ -54,4 +81,22 @@ typedef int socklen_t;
|
|||||||
|
|
||||||
#define MG_INT64_FMT "%I64d"
|
#define MG_INT64_FMT "%I64d"
|
||||||
|
|
||||||
|
static __inline FILE *mg_fopen(const char *path, const char *mode) {
|
||||||
|
wchar_t b1[PATH_MAX], b2[10];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
|
||||||
|
return _wfopen(b1, b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
|
||||||
|
static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
|
||||||
|
(void) tm;
|
||||||
|
return gmtime(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
|
||||||
|
(void) tm;
|
||||||
|
return localtime(t);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+10
-10
@@ -31,16 +31,16 @@ static int mg_b64rev(int c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mg_base64_update(unsigned char ch, char *to, int n) {
|
int mg_base64_update(unsigned char ch, char *to, int n) {
|
||||||
unsigned char rem = (n & 3) % 3;
|
int rem = (n & 3) % 3;
|
||||||
if (rem == 0) {
|
if (rem == 0) {
|
||||||
to[n] = mg_b64idx(ch >> 2);
|
to[n] = (char) mg_b64idx(ch >> 2);
|
||||||
to[++n] = (ch & 3) << 4;
|
to[++n] = (char) ((ch & 3) << 4);
|
||||||
} else if (rem == 1) {
|
} else if (rem == 1) {
|
||||||
to[n] = mg_b64idx(to[n] | (ch >> 4));
|
to[n] = (char) mg_b64idx(to[n] | (ch >> 4));
|
||||||
to[++n] = (ch & 15) << 2;
|
to[++n] = (char) ((ch & 15) << 2);
|
||||||
} else {
|
} else {
|
||||||
to[n] = mg_b64idx(to[n] | (ch >> 6));
|
to[n] = (char) mg_b64idx(to[n] | (ch >> 6));
|
||||||
to[++n] = mg_b64idx(ch & 63);
|
to[++n] = (char) mg_b64idx(ch & 63);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
@@ -71,10 +71,10 @@ int mg_base64_decode(const char *src, int n, char *dst) {
|
|||||||
int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]),
|
int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]),
|
||||||
d = mg_b64rev(src[3]);
|
d = mg_b64rev(src[3]);
|
||||||
if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
|
if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
|
||||||
dst[len++] = (a << 2) | (b >> 4);
|
dst[len++] = (char) ((a << 2) | (b >> 4));
|
||||||
if (src[2] != '=') {
|
if (src[2] != '=') {
|
||||||
dst[len++] = (b << 4) | (c >> 2);
|
dst[len++] = (char) ((b << 4) | (c >> 2));
|
||||||
if (src[3] != '=') dst[len++] = (c << 6) | d;
|
if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
|
||||||
}
|
}
|
||||||
src += 4;
|
src += 4;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-11
@@ -1,12 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef MG_ENABLE_LWIP
|
#ifndef MG_ENABLE_SOCKET
|
||||||
#define MG_ENABLE_LWIP 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_ENABLE_LWIP
|
|
||||||
#define MG_ENABLE_SOCKET 0
|
|
||||||
#elif !defined(MG_ENABLE_SOCKET)
|
|
||||||
#define MG_ENABLE_SOCKET 1
|
#define MG_ENABLE_SOCKET 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -34,14 +28,15 @@
|
|||||||
#define MG_ENABLE_LOG 1
|
#define MG_ENABLE_LOG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_MGOS
|
|
||||||
#define MG_ENABLE_MGOS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MG_ENABLE_MD5
|
#ifndef MG_ENABLE_MD5
|
||||||
#define MG_ENABLE_MD5 0
|
#define MG_ENABLE_MD5 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
|
||||||
|
#ifndef MG_ENABLE_WINSOCK
|
||||||
|
#define MG_ENABLE_WINSOCK 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_DIRECTORY_LISTING
|
#ifndef MG_ENABLE_DIRECTORY_LISTING
|
||||||
#define MG_ENABLE_DIRECTORY_LISTING 0
|
#define MG_ENABLE_DIRECTORY_LISTING 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -70,11 +70,10 @@ size_t mg_dns_parse_name(const uint8_t *s, size_t n, size_t ofs, char *dst,
|
|||||||
|
|
||||||
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
||||||
bool is_question, struct mg_dns_rr *rr) {
|
bool is_question, struct mg_dns_rr *rr) {
|
||||||
const struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
|
||||||
const uint8_t *s = buf + ofs, *e = &buf[len];
|
const uint8_t *s = buf + ofs, *e = &buf[len];
|
||||||
|
|
||||||
memset(rr, 0, sizeof(*rr));
|
memset(rr, 0, sizeof(*rr));
|
||||||
if (len < sizeof(*h)) return 0; // Too small, headers dont fit
|
if (len < sizeof(struct mg_dns_header)) return 0; // Too small
|
||||||
if (len > 512) return 0; // Too large, we don't expect that
|
if (len > 512) return 0; // Too large, we don't expect that
|
||||||
if (s >= e) return 0; // Overflow
|
if (s >= e) return 0; // Overflow
|
||||||
|
|
||||||
@@ -82,15 +81,15 @@ size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
|||||||
return 0;
|
return 0;
|
||||||
s += rr->nlen + 4;
|
s += rr->nlen + 4;
|
||||||
if (s > e) return 0;
|
if (s > e) return 0;
|
||||||
rr->atype = ((uint16_t) s[-4] << 8) | s[-3];
|
rr->atype = (uint16_t)(((uint16_t) s[-4] << 8) | s[-3]);
|
||||||
rr->aclass = ((uint16_t) s[-2] << 8) | s[-1];
|
rr->aclass = (uint16_t)(((uint16_t) s[-2] << 8) | s[-1]);
|
||||||
if (is_question) return rr->nlen + 4;
|
if (is_question) return (size_t)(rr->nlen + 4);
|
||||||
|
|
||||||
s += 6;
|
s += 6;
|
||||||
if (s > e) return 0;
|
if (s > e) return 0;
|
||||||
rr->alen = ((uint16_t) s[-2] << 8) | s[-1];
|
rr->alen = (uint16_t)(((uint16_t) s[-2] << 8) | s[-1]);
|
||||||
if (s + rr->alen > e) return 0;
|
if (s + rr->alen > e) return 0;
|
||||||
return rr->nlen + rr->alen + 10;
|
return (size_t)(rr->nlen + rr->alen + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
||||||
@@ -242,14 +241,18 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
|
|||||||
} else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
|
} else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
|
||||||
mg_error(c, "resolve OOM");
|
mg_error(c, "resolve OOM");
|
||||||
} else {
|
} else {
|
||||||
d->txnid = s_reqs ? s_reqs->txnid + 1 : 1;
|
#if MG_ENABLE_LOG
|
||||||
|
char buf[100];
|
||||||
|
#endif
|
||||||
|
d->txnid = s_reqs ? (uint16_t)(s_reqs->txnid + 1) : 1;
|
||||||
d->next = s_reqs;
|
d->next = s_reqs;
|
||||||
s_reqs = d;
|
s_reqs = d;
|
||||||
d->expire = mg_millis() + ms;
|
d->expire = mg_millis() + (unsigned long) ms;
|
||||||
d->c = c;
|
d->c = c;
|
||||||
c->is_resolving = 1;
|
c->is_resolving = 1;
|
||||||
LOG(LL_VERBOSE_DEBUG, ("%lu resolving %.*s, txnid %hu", c->id,
|
LOG(LL_VERBOSE_DEBUG,
|
||||||
(int) name->len, name->ptr, d->txnid));
|
("%lu resolving %.*s @ %s, txnid %hu", c->id, (int) name->len,
|
||||||
|
name->ptr, mg_ntoa(&dnsc->c->peer, buf, sizeof(buf)), d->txnid));
|
||||||
mg_dns_send(dnsc->c, name, d->txnid, ipv6);
|
mg_dns_send(dnsc->c, name, d->txnid, ipv6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ enum {
|
|||||||
MG_EV_CONNECT, // Connection established NULL
|
MG_EV_CONNECT, // Connection established NULL
|
||||||
MG_EV_ACCEPT, // Connection accepted NULL
|
MG_EV_ACCEPT, // Connection accepted NULL
|
||||||
MG_EV_READ, // Data received from socket struct mg_str *
|
MG_EV_READ, // Data received from socket struct mg_str *
|
||||||
MG_EV_WRITE, // Data written to socket int *num_bytes_written
|
MG_EV_WRITE, // Data written to socket long *bytes_written
|
||||||
MG_EV_CLOSE, // Connection closed NULL
|
MG_EV_CLOSE, // Connection closed NULL
|
||||||
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
|
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
|
||||||
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
|
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
|
||||||
|
|||||||
+310
-103
@@ -1,6 +1,6 @@
|
|||||||
|
#include "http.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "http.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
@@ -10,7 +10,56 @@
|
|||||||
#include "ws.h"
|
#include "ws.h"
|
||||||
|
|
||||||
// Multipart POST example:
|
// Multipart POST example:
|
||||||
// https://gist.github.com/cpq/b8dd247571e6ee9c54ef7e8dfcfecf48
|
// --xyz
|
||||||
|
// Content-Disposition: form-data; name="val"
|
||||||
|
//
|
||||||
|
// abcdef
|
||||||
|
// --xyz
|
||||||
|
// Content-Disposition: form-data; name="foo"; filename="a.txt"
|
||||||
|
// Content-Type: text/plain
|
||||||
|
//
|
||||||
|
// hello world
|
||||||
|
//
|
||||||
|
// --xyz--
|
||||||
|
size_t mg_http_next_multipart(struct mg_str body, size_t ofs,
|
||||||
|
struct mg_http_part *part) {
|
||||||
|
struct mg_str cd = mg_str_n("Content-Disposition", 19);
|
||||||
|
const char *s = body.ptr;
|
||||||
|
size_t b = ofs, h1, h2, b1, b2, max = body.len;
|
||||||
|
|
||||||
|
// Init part params
|
||||||
|
if (part != NULL) part->name = part->filename = part->body = mg_str_n(0, 0);
|
||||||
|
|
||||||
|
// Skip boundary
|
||||||
|
while (b + 2 < max && s[b] != '\r' && s[b + 1] != '\n') b++;
|
||||||
|
if (b <= ofs || b + 2 >= max) return 0;
|
||||||
|
// LOG(LL_INFO, ("B: %zu %zu [%.*s]", ofs, b - ofs, (int) (b - ofs), s));
|
||||||
|
|
||||||
|
// Skip headers
|
||||||
|
h1 = h2 = b + 2;
|
||||||
|
for (;;) {
|
||||||
|
while (h2 + 2 < max && s[h2] != '\r' && s[h2 + 1] != '\n') h2++;
|
||||||
|
if (h2 == h1) break;
|
||||||
|
if (h2 + 2 >= max) return 0;
|
||||||
|
// LOG(LL_INFO, ("Header: [%.*s]", (int) (h2 - h1), &s[h1]));
|
||||||
|
if (part != NULL && h1 + cd.len + 2 < h2 && s[h1 + cd.len] == ':' &&
|
||||||
|
mg_ncasecmp(&s[h1], cd.ptr, cd.len) == 0) {
|
||||||
|
struct mg_str v = mg_str_n(&s[h1 + cd.len + 2], h2 - (h1 + cd.len + 2));
|
||||||
|
part->name = mg_http_get_header_var(v, mg_str_n("name", 4));
|
||||||
|
part->filename = mg_http_get_header_var(v, mg_str_n("filename", 8));
|
||||||
|
}
|
||||||
|
h1 = h2 = h2 + 2;
|
||||||
|
}
|
||||||
|
b1 = b2 = h2 + 2;
|
||||||
|
while (b2 + 2 + (b - ofs) + 2 < max && !(s[b2] == '\r' && s[b2 + 1] == '\n' &&
|
||||||
|
memcmp(&s[b2 + 2], s, b - ofs) == 0))
|
||||||
|
b2++;
|
||||||
|
|
||||||
|
if (b2 + 2 >= max) return 0;
|
||||||
|
if (part != NULL) part->body = mg_str_n(&s[b1], b2 - b1);
|
||||||
|
// LOG(LL_INFO, ("Body: [%.*s]", (int) (b2 - b1), &s[b1]));
|
||||||
|
return b2 + 2;
|
||||||
|
}
|
||||||
|
|
||||||
void mg_http_bauth(struct mg_connection *c, const char *user,
|
void mg_http_bauth(struct mg_connection *c, const char *user,
|
||||||
const char *pass) {
|
const char *pass) {
|
||||||
@@ -18,16 +67,20 @@ void mg_http_bauth(struct mg_connection *c, const char *user,
|
|||||||
size_t need = c->send.len + 36 + (u.len + p.len) * 2;
|
size_t need = c->send.len + 36 + (u.len + p.len) * 2;
|
||||||
if (c->send.size < need) mg_iobuf_resize(&c->send, need);
|
if (c->send.size < need) mg_iobuf_resize(&c->send, need);
|
||||||
if (c->send.size >= need) {
|
if (c->send.size >= need) {
|
||||||
size_t i, n = 0;
|
int i, n = 0;
|
||||||
char *buf = (char *) &c->send.buf[c->send.len + 21];
|
char *buf = (char *) &c->send.buf[c->send.len + 21];
|
||||||
memcpy(&buf[-21], "Authorization: Basic ", 21); // DON'T use mg_send!
|
memcpy(&buf[-21], "Authorization: Basic ", 21); // DON'T use mg_send!
|
||||||
for (i = 0; i < u.len; i++) n = mg_base64_update(u.ptr[i], buf, n);
|
for (i = 0; i < (int) u.len; i++) {
|
||||||
|
n = mg_base64_update(((unsigned char *) u.ptr)[i], buf, n);
|
||||||
|
}
|
||||||
if (p.len > 0) {
|
if (p.len > 0) {
|
||||||
n = mg_base64_update(':', buf, n);
|
n = mg_base64_update(':', buf, n);
|
||||||
for (i = 0; i < p.len; i++) n = mg_base64_update(p.ptr[i], buf, n);
|
for (i = 0; i < (int) p.len; i++) {
|
||||||
|
n = mg_base64_update(((unsigned char *) p.ptr)[i], buf, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n = mg_base64_final(buf, n);
|
n = mg_base64_final(buf, n);
|
||||||
c->send.len += 21 + n + 2;
|
c->send.len += 21 + (size_t) n + 2;
|
||||||
memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2);
|
memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2);
|
||||||
} else {
|
} else {
|
||||||
LOG(LL_ERROR, ("%lu %s cannot resize iobuf %d->%d ", c->id, c->label,
|
LOG(LL_ERROR, ("%lu %s cannot resize iobuf %d->%d ", c->id, c->label,
|
||||||
@@ -36,7 +89,7 @@ void mg_http_bauth(struct mg_connection *c, const char *user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
|
int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
|
||||||
int dst_len) {
|
size_t dst_len) {
|
||||||
const char *p, *e, *s;
|
const char *p, *e, *s;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
int len;
|
int len;
|
||||||
@@ -105,7 +158,7 @@ static const char *skip(const char *s, const char *e, const char *d,
|
|||||||
struct mg_str *v) {
|
struct mg_str *v) {
|
||||||
v->ptr = s;
|
v->ptr = s;
|
||||||
while (s < e && *s != '\n' && strchr(d, *s) == NULL) s++;
|
while (s < e && *s != '\n' && strchr(d, *s) == NULL) s++;
|
||||||
v->len = s - v->ptr;
|
v->len = (size_t)(s - v->ptr);
|
||||||
while (s < e && strchr(d, *s) != NULL) s++;
|
while (s < e && strchr(d, *s) != NULL) s++;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -147,7 +200,7 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
|||||||
|
|
||||||
hm->message.ptr = hm->head.ptr = s;
|
hm->message.ptr = hm->head.ptr = s;
|
||||||
hm->body.ptr = end;
|
hm->body.ptr = end;
|
||||||
hm->head.len = req_len;
|
hm->head.len = (size_t) req_len;
|
||||||
hm->chunk.ptr = end;
|
hm->chunk.ptr = end;
|
||||||
hm->message.len = hm->body.len = (size_t) ~0; // Set body length to infinite
|
hm->message.len = hm->body.len = (size_t) ~0; // Set body length to infinite
|
||||||
|
|
||||||
@@ -156,21 +209,21 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
|||||||
s = skip(s, end, " ", &hm->uri);
|
s = skip(s, end, " ", &hm->uri);
|
||||||
s = skip(s, end, "\r\n", &hm->proto);
|
s = skip(s, end, "\r\n", &hm->proto);
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check. Allow protocol/reason to be empty
|
||||||
if (hm->method.len == 0 || hm->uri.len == 0 || hm->proto.len == 0) return -1;
|
if (hm->method.len == 0 || hm->uri.len == 0) return -1;
|
||||||
|
|
||||||
// If URI contains '?' character, setup query string
|
// If URI contains '?' character, setup query string
|
||||||
if ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) {
|
if ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) {
|
||||||
hm->query.ptr = qs + 1;
|
hm->query.ptr = qs + 1;
|
||||||
hm->query.len = &hm->uri.ptr[hm->uri.len] - (qs + 1);
|
hm->query.len = (size_t)(&hm->uri.ptr[hm->uri.len] - (qs + 1));
|
||||||
hm->uri.len = qs - hm->uri.ptr;
|
hm->uri.len = (size_t)(qs - hm->uri.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_http_parse_headers(s, end, hm->headers,
|
mg_http_parse_headers(s, end, hm->headers,
|
||||||
sizeof(hm->headers) / sizeof(hm->headers[0]));
|
sizeof(hm->headers) / sizeof(hm->headers[0]));
|
||||||
if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
|
if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
|
||||||
hm->body.len = (size_t) mg_to64(*cl);
|
hm->body.len = (size_t) mg_to64(*cl);
|
||||||
hm->message.len = req_len + hm->body.len;
|
hm->message.len = (size_t) req_len + hm->body.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mg_http_parse() is used to parse both HTTP requests and HTTP
|
// mg_http_parse() is used to parse both HTTP requests and HTTP
|
||||||
@@ -190,14 +243,14 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
|||||||
mg_vcasecmp(&hm->method, "PUT") != 0 &&
|
mg_vcasecmp(&hm->method, "PUT") != 0 &&
|
||||||
mg_vcasecmp(&hm->method, "POST") != 0) {
|
mg_vcasecmp(&hm->method, "POST") != 0) {
|
||||||
hm->body.len = 0;
|
hm->body.len = 0;
|
||||||
hm->message.len = req_len;
|
hm->message.len = (size_t) req_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The 204 (No content) responses also have 0 body length
|
// The 204 (No content) responses also have 0 body length
|
||||||
if (hm->body.len == (size_t) ~0 && is_response &&
|
if (hm->body.len == (size_t) ~0 && is_response &&
|
||||||
mg_vcasecmp(&hm->uri, "204") == 0) {
|
mg_vcasecmp(&hm->uri, "204") == 0) {
|
||||||
hm->body.len = 0;
|
hm->body.len = 0;
|
||||||
hm->message.len = req_len;
|
hm->message.len = (size_t) req_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return req_len;
|
return req_len;
|
||||||
@@ -208,7 +261,7 @@ static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
|
|||||||
char mem[256], *buf = mem;
|
char mem[256], *buf = mem;
|
||||||
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||||
mg_printf(c, "%X\r\n", len);
|
mg_printf(c, "%X\r\n", len);
|
||||||
mg_send(c, buf, len);
|
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||||
mg_send(c, "\r\n", 2);
|
mg_send(c, "\r\n", 2);
|
||||||
if (buf != mem) free(buf);
|
if (buf != mem) free(buf);
|
||||||
}
|
}
|
||||||
@@ -221,11 +274,82 @@ void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
|
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
|
||||||
mg_printf(c, "%X\r\n", len);
|
mg_printf(c, "%lX\r\n", (unsigned long) len);
|
||||||
mg_send(c, buf, len);
|
mg_send(c, buf, len);
|
||||||
mg_send(c, "\r\n", 2);
|
mg_send(c, "\r\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static const char *mg_http_status_code_str(int status_code) {
|
||||||
|
switch (status_code) {
|
||||||
|
case 100: return "Continue";
|
||||||
|
case 101: return "Switching Protocols";
|
||||||
|
case 102: return "Processing";
|
||||||
|
case 200: return "OK";
|
||||||
|
case 201: return "Created";
|
||||||
|
case 202: return "Accepted";
|
||||||
|
case 203: return "Non-authoritative Information";
|
||||||
|
case 204: return "No Content";
|
||||||
|
case 205: return "Reset Content";
|
||||||
|
case 206: return "Partial Content";
|
||||||
|
case 207: return "Multi-Status";
|
||||||
|
case 208: return "Already Reported";
|
||||||
|
case 226: return "IM Used";
|
||||||
|
case 300: return "Multiple Choices";
|
||||||
|
case 301: return "Moved Permanently";
|
||||||
|
case 302: return "Found";
|
||||||
|
case 303: return "See Other";
|
||||||
|
case 304: return "Not Modified";
|
||||||
|
case 305: return "Use Proxy";
|
||||||
|
case 307: return "Temporary Redirect";
|
||||||
|
case 308: return "Permanent Redirect";
|
||||||
|
case 400: return "Bad Request";
|
||||||
|
case 401: return "Unauthorized";
|
||||||
|
case 402: return "Payment Required";
|
||||||
|
case 403: return "Forbidden";
|
||||||
|
case 404: return "Not Found";
|
||||||
|
case 405: return "Method Not Allowed";
|
||||||
|
case 406: return "Not Acceptable";
|
||||||
|
case 407: return "Proxy Authentication Required";
|
||||||
|
case 408: return "Request Timeout";
|
||||||
|
case 409: return "Conflict";
|
||||||
|
case 410: return "Gone";
|
||||||
|
case 411: return "Length Required";
|
||||||
|
case 412: return "Precondition Failed";
|
||||||
|
case 413: return "Payload Too Large";
|
||||||
|
case 414: return "Request-URI Too Long";
|
||||||
|
case 415: return "Unsupported Media Type";
|
||||||
|
case 416: return "Requested Range Not Satisfiable";
|
||||||
|
case 417: return "Expectation Failed";
|
||||||
|
case 418: return "I'm a teapot";
|
||||||
|
case 421: return "Misdirected Request";
|
||||||
|
case 422: return "Unprocessable Entity";
|
||||||
|
case 423: return "Locked";
|
||||||
|
case 424: return "Failed Dependency";
|
||||||
|
case 426: return "Upgrade Required";
|
||||||
|
case 428: return "Precondition Required";
|
||||||
|
case 429: return "Too Many Requests";
|
||||||
|
case 431: return "Request Header Fields Too Large";
|
||||||
|
case 444: return "Connection Closed Without Response";
|
||||||
|
case 451: return "Unavailable For Legal Reasons";
|
||||||
|
case 499: return "Client Closed Request";
|
||||||
|
case 500: return "Internal Server Error";
|
||||||
|
case 501: return "Not Implemented";
|
||||||
|
case 502: return "Bad Gateway";
|
||||||
|
case 503: return "Service Unavailable";
|
||||||
|
case 504: return "Gateway Timeout";
|
||||||
|
case 505: return "HTTP Version Not Supported";
|
||||||
|
case 506: return "Variant Also Negotiates";
|
||||||
|
case 507: return "Insufficient Storage";
|
||||||
|
case 508: return "Loop Detected";
|
||||||
|
case 510: return "Not Extended";
|
||||||
|
case 511: return "Network Authentication Required";
|
||||||
|
case 599: return "Network Connect Timeout Error";
|
||||||
|
default: return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
||||||
const char *fmt, ...) {
|
const char *fmt, ...) {
|
||||||
char mem[100], *buf = mem;
|
char mem[100], *buf = mem;
|
||||||
@@ -234,9 +358,9 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
|||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
mg_printf(c, "HTTP/1.1 %d OK\r\n%sContent-Length: %d\r\n\r\n", code,
|
mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code,
|
||||||
headers == NULL ? "" : headers, len);
|
mg_http_status_code_str(code), headers == NULL ? "" : headers, len);
|
||||||
mg_send(c, buf, len);
|
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||||
if (buf != mem) free(buf);
|
if (buf != mem) free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,14 +392,14 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);
|
snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);
|
||||||
LOG(LL_DEBUG,
|
LOG(LL_DEBUG,
|
||||||
("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
|
("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
|
||||||
if ((fp = mg_fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
|
if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
|
||||||
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
|
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
|
||||||
return -2;
|
return -2;
|
||||||
} else {
|
} else {
|
||||||
fwrite(hm->body.ptr, 1, hm->body.len, fp);
|
fwrite(hm->body.ptr, 1, hm->body.len, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
mg_http_reply(c, 200, "", "");
|
mg_http_reply(c, 200, "", "");
|
||||||
return hm->body.len;
|
return (int) hm->body.len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,46 +432,53 @@ static const char *guess_content_type(const char *filename) {
|
|||||||
} * t, types[] = {
|
} * t, types[] = {
|
||||||
MIME_ENTRY("html", "text/html; charset=utf-8"),
|
MIME_ENTRY("html", "text/html; charset=utf-8"),
|
||||||
MIME_ENTRY("htm", "text/html; charset=utf-8"),
|
MIME_ENTRY("htm", "text/html; charset=utf-8"),
|
||||||
MIME_ENTRY("shtml", "text/html; charset=utf-8"),
|
MIME_ENTRY("css", "text/css; charset=utf-8"),
|
||||||
MIME_ENTRY("css", "text/css"),
|
MIME_ENTRY("js", "text/javascript; charset=utf-8"),
|
||||||
MIME_ENTRY("js", "text/javascript"),
|
|
||||||
MIME_ENTRY("mjs", "text/javascript"),
|
|
||||||
MIME_ENTRY("json", "application/json"),
|
|
||||||
MIME_ENTRY("ico", "image/x-icon"),
|
|
||||||
MIME_ENTRY("gif", "image/gif"),
|
MIME_ENTRY("gif", "image/gif"),
|
||||||
MIME_ENTRY("jpg", "image/jpeg"),
|
|
||||||
MIME_ENTRY("jpeg", "image/jpeg"),
|
|
||||||
MIME_ENTRY("png", "image/png"),
|
MIME_ENTRY("png", "image/png"),
|
||||||
MIME_ENTRY("svg", "image/svg+xml"),
|
MIME_ENTRY("woff", "font/woff"),
|
||||||
MIME_ENTRY("txt", "text/plain; charset=utf-8"),
|
|
||||||
MIME_ENTRY("wav", "audio/wav"),
|
|
||||||
MIME_ENTRY("mp3", "audio/mpeg"),
|
|
||||||
MIME_ENTRY("mid", "audio/mid"),
|
|
||||||
MIME_ENTRY("ogg", "application/ogg"),
|
|
||||||
MIME_ENTRY("xml", "application/xml"),
|
|
||||||
MIME_ENTRY("ttf", "font/ttf"),
|
MIME_ENTRY("ttf", "font/ttf"),
|
||||||
MIME_ENTRY("json", "application/json"),
|
MIME_ENTRY("aac", "audio/aac"),
|
||||||
MIME_ENTRY("xsl", "application/xml"),
|
MIME_ENTRY("avi", "video/x-msvideo"),
|
||||||
|
MIME_ENTRY("azw", "application/vnd.amazon.ebook"),
|
||||||
|
MIME_ENTRY("bin", "application/octet-stream"),
|
||||||
|
MIME_ENTRY("bmp", "image/bmp"),
|
||||||
|
MIME_ENTRY("bz", "application/x-bzip"),
|
||||||
|
MIME_ENTRY("bz2", "application/x-bzip2"),
|
||||||
|
MIME_ENTRY("csv", "text/csv"),
|
||||||
MIME_ENTRY("doc", "application/msword"),
|
MIME_ENTRY("doc", "application/msword"),
|
||||||
|
MIME_ENTRY("epub", "application/epub+zip"),
|
||||||
MIME_ENTRY("exe", "application/octet-stream"),
|
MIME_ENTRY("exe", "application/octet-stream"),
|
||||||
MIME_ENTRY("zip", "application/zip"),
|
|
||||||
MIME_ENTRY("xls", "application/excel"),
|
|
||||||
MIME_ENTRY("tgz", "application/tar-gz"),
|
|
||||||
MIME_ENTRY("tar", "application/tar"),
|
|
||||||
MIME_ENTRY("gz", "application/gzip"),
|
MIME_ENTRY("gz", "application/gzip"),
|
||||||
|
MIME_ENTRY("ico", "image/x-icon"),
|
||||||
|
MIME_ENTRY("json", "application/json"),
|
||||||
|
MIME_ENTRY("mid", "audio/mid"),
|
||||||
|
MIME_ENTRY("mjs", "text/javascript"),
|
||||||
|
MIME_ENTRY("mov", "video/quicktime"),
|
||||||
|
MIME_ENTRY("mp3", "audio/mpeg"),
|
||||||
|
MIME_ENTRY("mp4", "video/mp4"),
|
||||||
|
MIME_ENTRY("mpeg", "video/mpeg"),
|
||||||
|
MIME_ENTRY("mpg", "video/mpeg"),
|
||||||
|
MIME_ENTRY("ogg", "application/ogg"),
|
||||||
|
MIME_ENTRY("pdf", "application/pdf"),
|
||||||
MIME_ENTRY("rar", "application/rar"),
|
MIME_ENTRY("rar", "application/rar"),
|
||||||
MIME_ENTRY("rtf", "application/rtf"),
|
MIME_ENTRY("rtf", "application/rtf"),
|
||||||
MIME_ENTRY("pdf", "application/pdf"),
|
MIME_ENTRY("shtml", "text/html; charset=utf-8"),
|
||||||
MIME_ENTRY("mpg", "video/mpeg"),
|
MIME_ENTRY("svg", "image/svg+xml"),
|
||||||
MIME_ENTRY("webm", "video/webm"),
|
MIME_ENTRY("tar", "application/tar"),
|
||||||
MIME_ENTRY("mpeg", "video/mpeg"),
|
MIME_ENTRY("tgz", "application/tar-gz"),
|
||||||
MIME_ENTRY("mov", "video/quicktime"),
|
MIME_ENTRY("txt", "text/plain; charset=utf-8"),
|
||||||
MIME_ENTRY("mp4", "video/mp4"),
|
|
||||||
MIME_ENTRY("avi", "video/x-msvideo"),
|
|
||||||
MIME_ENTRY("csv", "text/csv"),
|
|
||||||
MIME_ENTRY("bmp", "image/bmp"),
|
|
||||||
MIME_ENTRY("bin", "application/octet-stream"),
|
|
||||||
MIME_ENTRY("wasm", "application/wasm"),
|
MIME_ENTRY("wasm", "application/wasm"),
|
||||||
|
MIME_ENTRY("wav", "audio/wav"),
|
||||||
|
MIME_ENTRY("weba", "audio/webm"),
|
||||||
|
MIME_ENTRY("webm", "video/webm"),
|
||||||
|
MIME_ENTRY("webp", "image/webp"),
|
||||||
|
MIME_ENTRY("xls", "application/excel"),
|
||||||
|
MIME_ENTRY("xml", "application/xml"),
|
||||||
|
MIME_ENTRY("xsl", "application/xml"),
|
||||||
|
MIME_ENTRY("zip", "application/zip"),
|
||||||
|
MIME_ENTRY("3gp", "video/3gpp"),
|
||||||
|
MIME_ENTRY("7z", "application/x-7z-compressed"),
|
||||||
{NULL, 0, NULL},
|
{NULL, 0, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -359,26 +490,78 @@ static const char *guess_content_type(const char *filename) {
|
|||||||
return "text/plain; charset=utf-8";
|
return "text/plain; charset=utf-8";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getrange(struct mg_str *s, int64_t *a, int64_t *b) {
|
||||||
|
size_t i, numparsed = 0;
|
||||||
|
LOG(LL_INFO, ("%.*s", (int) s->len, s->ptr));
|
||||||
|
for (i = 0; i + 6 < s->len; i++) {
|
||||||
|
if (memcmp(&s->ptr[i], "bytes=", 6) == 0) {
|
||||||
|
struct mg_str p = mg_str_n(s->ptr + i + 6, s->len - i - 6);
|
||||||
|
if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
|
||||||
|
*a = mg_to64(p);
|
||||||
|
// LOG(LL_INFO, ("PPP [%.*s] %d", (int) p.len, p.ptr, numparsed));
|
||||||
|
while (p.len && p.ptr[0] >= '0' && p.ptr[0] <= '9') p.ptr++, p.len--;
|
||||||
|
if (p.len && p.ptr[0] == '-') p.ptr++, p.len--;
|
||||||
|
*b = mg_to64(p);
|
||||||
|
if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
|
||||||
|
// LOG(LL_INFO, ("PPP [%.*s] %d", (int) p.len, p.ptr, numparsed));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (int) numparsed;
|
||||||
|
}
|
||||||
|
|
||||||
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||||
const char *path, const char *mime, const char *hdrs) {
|
const char *path, const char *mime, const char *hdrs) {
|
||||||
struct mg_str *inm = mg_http_get_header(hm, "If-None-Match");
|
struct mg_str *inm = mg_http_get_header(hm, "If-None-Match");
|
||||||
mg_stat_t st;
|
mg_stat_t st;
|
||||||
char etag[64];
|
char etag[64];
|
||||||
FILE *fp = mg_fopen(path, "rb");
|
FILE *fp = fopen(path, "rb");
|
||||||
if (fp == NULL || mg_stat(path, &st) != 0 ||
|
if (fp == NULL || mg_stat(path, &st) != 0 ||
|
||||||
mg_http_etag(etag, sizeof(etag), &st) != etag) {
|
mg_http_etag(etag, sizeof(etag), &st) != etag) {
|
||||||
LOG(LL_DEBUG,
|
LOG(LL_DEBUG, ("404 [%.*s] [%s] %p", (int) hm->uri.len, hm->uri.ptr, path,
|
||||||
("404 [%.*s] [%s] %p", (int) hm->uri.len, hm->uri.ptr, path, fp));
|
(void *) fp));
|
||||||
mg_http_reply(c, 404, "", "%s", "Not found\n");
|
mg_http_reply(c, 404, "", "%s", "Not found\n");
|
||||||
if (fp != NULL) fclose(fp);
|
if (fp != NULL) fclose(fp);
|
||||||
} else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) {
|
} else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
|
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
|
||||||
} else {
|
} else {
|
||||||
|
int n, status = 200;
|
||||||
|
char range[100] = "";
|
||||||
|
int64_t r1 = 0, r2 = 0, cl = st.st_size;
|
||||||
|
|
||||||
|
// Handle Range header
|
||||||
|
struct mg_str *rh = mg_http_get_header(hm, "Range");
|
||||||
|
if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0 && r1 >= 0 && r2 >= 0) {
|
||||||
|
// If range is specified like "400-", set second limit to content len
|
||||||
|
if (n == 1) r2 = cl - 1;
|
||||||
|
if (r1 > r2 || r2 >= cl) {
|
||||||
|
status = 416;
|
||||||
|
cl = 0;
|
||||||
|
snprintf(range, sizeof(range),
|
||||||
|
"Content-Range: bytes */" MG_INT64_FMT "\r\n",
|
||||||
|
(int64_t) st.st_size);
|
||||||
|
} else {
|
||||||
|
status = 206;
|
||||||
|
cl = r2 - r1 + 1;
|
||||||
|
snprintf(range, sizeof(range),
|
||||||
|
"Content-Range: bytes " MG_INT64_FMT "-" MG_INT64_FMT
|
||||||
|
"/" MG_INT64_FMT "\r\n",
|
||||||
|
r1, r1 + cl - 1, (int64_t) st.st_size);
|
||||||
|
#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
|
||||||
|
_XOPEN_SOURCE >= 600
|
||||||
|
fseeko(fp, (off_t) r1, SEEK_SET);
|
||||||
|
#else
|
||||||
|
fseek(fp, (long) r1, SEEK_SET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mg_printf(c,
|
mg_printf(c,
|
||||||
"HTTP/1.1 200 OK\r\nContent-Type: %s\r\n"
|
"HTTP/1.1 %d %s\r\nContent-Type: %s\r\n"
|
||||||
"Etag: %s\r\nContent-Length: " MG_INT64_FMT "\r\n%s\r\n",
|
"Etag: %s\r\nContent-Length: " MG_INT64_FMT "\r\n%s%s\r\n",
|
||||||
mime, etag, (int64_t) st.st_size, hdrs ? hdrs : "");
|
status, mg_http_status_code_str(status), mime, etag, cl, range,
|
||||||
|
hdrs ? hdrs : "");
|
||||||
if (mg_vcasecmp(&hm->method, "HEAD") == 0) {
|
if (mg_vcasecmp(&hm->method, "HEAD") == 0) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
} else {
|
} else {
|
||||||
@@ -389,7 +572,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_ESP32 || MG_ARCH == MG_ARCH_ESP8266 || \
|
#if MG_ARCH == MG_ARCH_ESP32 || MG_ARCH == MG_ARCH_ESP8266 || \
|
||||||
MG_ARCH == MG_ARCH_FREERTOS
|
MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
char *realpath(const char *src, char *dst) {
|
char *realpath(const char *src, char *dst) {
|
||||||
int len = strlen(src);
|
int len = strlen(src);
|
||||||
if (len > MG_PATH_MAX - 1) len = MG_PATH_MAX - 1;
|
if (len > MG_PATH_MAX - 1) len = MG_PATH_MAX - 1;
|
||||||
@@ -403,7 +586,7 @@ char *realpath(const char *src, char *dst) {
|
|||||||
// Allow user to override this function
|
// Allow user to override this function
|
||||||
bool mg_is_dir(const char *path) WEAK;
|
bool mg_is_dir(const char *path) WEAK;
|
||||||
bool mg_is_dir(const char *path) {
|
bool mg_is_dir(const char *path) {
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP && defined(MG_ENABLE_FF)
|
||||||
struct FF_STAT st;
|
struct FF_STAT st;
|
||||||
return (ff_stat(path, &st) == 0) && (st.st_mode & FF_IFDIR);
|
return (ff_stat(path, &st) == 0) && (st.st_mode & FF_IFDIR);
|
||||||
#else
|
#else
|
||||||
@@ -471,7 +654,7 @@ DIR *opendir(const char *name) {
|
|||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||||
} else if ((d = (DIR *) malloc(sizeof(*d))) == NULL) {
|
} else if ((d = (DIR *) calloc(1, sizeof(*d))) == NULL) {
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
} else {
|
} else {
|
||||||
to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
|
to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
|
||||||
@@ -528,6 +711,7 @@ static void printdirentry(struct mg_connection *c, const char *name,
|
|||||||
char size[64], mod[64], path[MG_PATH_MAX];
|
char size[64], mod[64], path[MG_PATH_MAX];
|
||||||
int is_dir = S_ISDIR(stp->st_mode), n = 0;
|
int is_dir = S_ISDIR(stp->st_mode), n = 0;
|
||||||
const char *slash = is_dir ? "/" : "";
|
const char *slash = is_dir ? "/" : "";
|
||||||
|
struct tm t;
|
||||||
|
|
||||||
if (is_dir) {
|
if (is_dir) {
|
||||||
snprintf(size, sizeof(size), "%s", "[DIR]");
|
snprintf(size, sizeof(size), "%s", "[DIR]");
|
||||||
@@ -542,8 +726,8 @@ static void printdirentry(struct mg_connection *c, const char *name,
|
|||||||
snprintf(size, sizeof(size), "%.1fG", (double) stp->st_size / 1073741824);
|
snprintf(size, sizeof(size), "%.1fG", (double) stp->st_size / 1073741824);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime));
|
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime_r(&stp->st_mtime, &t));
|
||||||
n = mg_url_encode(name, strlen(name), path, sizeof(path));
|
n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
|
||||||
mg_printf(c,
|
mg_printf(c,
|
||||||
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
|
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
|
||||||
"<td>%s</td><td>%s</td></tr>\n",
|
"<td>%s</td><td>%s</td></tr>\n",
|
||||||
@@ -551,7 +735,7 @@ static void printdirentry(struct mg_connection *c, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
||||||
char *dir) {
|
struct mg_http_serve_opts *opts, char *dir) {
|
||||||
char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10];
|
char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10];
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
@@ -582,10 +766,12 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
while (p > dir && *p != '/') *p-- = '\0';
|
while (p > dir && *p != '/') *p-- = '\0';
|
||||||
if ((dirp = (opendir(dir))) != NULL) {
|
if ((dirp = (opendir(dir))) != NULL) {
|
||||||
size_t off, n;
|
size_t off, n;
|
||||||
mg_printf(c, "%s\r\n",
|
mg_printf(c,
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
"Content-Type: text/html; charset=utf-8\r\n"
|
"Content-Type: text/html; charset=utf-8\r\n"
|
||||||
"Content-Length: \r\n");
|
"%s"
|
||||||
|
"Content-Length: \r\n\r\n",
|
||||||
|
opts->extra_headers == NULL ? "" : opts->extra_headers);
|
||||||
off = c->send.len; // Start of body
|
off = c->send.len; // Start of body
|
||||||
mg_printf(c,
|
mg_printf(c,
|
||||||
"<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
|
"<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
|
||||||
@@ -620,7 +806,9 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
"</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
|
"</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
|
||||||
"</table><address>Mongoose v.%s</address></body></html>\n",
|
"</table><address>Mongoose v.%s</address></body></html>\n",
|
||||||
MG_VERSION);
|
MG_VERSION);
|
||||||
n = snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) (c->send.len - off));
|
n = (size_t) snprintf(tmp, sizeof(tmp), "%lu",
|
||||||
|
(unsigned long) (c->send.len - off));
|
||||||
|
if (n > sizeof(tmp)) n = 0;
|
||||||
memcpy(c->send.buf + off - 10, tmp, n); // Set content length
|
memcpy(c->send.buf + off - 10, tmp, n); // Set content length
|
||||||
} else {
|
} else {
|
||||||
mg_http_reply(c, 400, "", "Cannot open dir");
|
mg_http_reply(c, 400, "", "Cannot open dir");
|
||||||
@@ -668,19 +856,19 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
mg_http_reply(c, 404, "", "Invalid URI [%.*s]\n", (int) hm->uri.len,
|
mg_http_reply(c, 404, "", "Invalid URI [%.*s]\n", (int) hm->uri.len,
|
||||||
hm->uri.ptr);
|
hm->uri.ptr);
|
||||||
} else {
|
} else {
|
||||||
FILE *fp = mg_fopen(t2, "r");
|
FILE *fp = fopen(t2, "r");
|
||||||
#if MG_ENABLE_SSI
|
#if MG_ENABLE_SSI
|
||||||
if (is_index && fp == NULL) {
|
if (is_index && fp == NULL) {
|
||||||
char *p = t2 + strlen(t2);
|
char *p = t2 + strlen(t2);
|
||||||
while (p > t2 && p[-1] != '/') p--;
|
while (p > t2 && p[-1] != '/') p--;
|
||||||
strncpy(p, "index.shtml", &t2[sizeof(t2)] - p - 2);
|
strncpy(p, "index.shtml", (size_t)(&t2[sizeof(t2)] - p - 2));
|
||||||
t2[sizeof(t2) - 1] = '\0';
|
t2[sizeof(t2) - 1] = '\0';
|
||||||
fp = mg_fopen(t2, "r");
|
fp = fopen(t2, "r");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (is_index && fp == NULL) {
|
if (is_index && fp == NULL) {
|
||||||
#if MG_ENABLE_DIRECTORY_LISTING
|
#if MG_ENABLE_DIRECTORY_LISTING
|
||||||
listdir(c, hm, t2);
|
listdir(c, hm, opts, t2);
|
||||||
#else
|
#else
|
||||||
mg_http_reply(c, 403, "", "%s", "Directory listing not supported");
|
mg_http_reply(c, 403, "", "%s", "Directory listing not supported");
|
||||||
#endif
|
#endif
|
||||||
@@ -692,7 +880,8 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
mg_http_serve_ssi(c, t1, t2);
|
mg_http_serve_ssi(c, t1, t2);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
mg_http_serve_file(c, hm, t2, guess_content_type(t2), NULL);
|
mg_http_serve_file(c, hm, t2, guess_content_type(t2),
|
||||||
|
opts->extra_headers);
|
||||||
}
|
}
|
||||||
if (fp != NULL) fclose(fp);
|
if (fp != NULL) fclose(fp);
|
||||||
}
|
}
|
||||||
@@ -705,7 +894,7 @@ static bool mg_is_url_safe(int c) {
|
|||||||
(c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
|
(c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
|
size_t mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
|
||||||
size_t i, n = 0;
|
size_t i, n = 0;
|
||||||
for (i = 0; i < sl; i++) {
|
for (i = 0; i < sl; i++) {
|
||||||
int c = *(unsigned char *) &s[i];
|
int c = *(unsigned char *) &s[i];
|
||||||
@@ -721,14 +910,14 @@ int mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_http_creds(struct mg_http_message *hm, char *user, int userlen,
|
void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
|
||||||
char *pass, int passlen) {
|
char *pass, size_t passlen) {
|
||||||
struct mg_str *v = mg_http_get_header(hm, "Authorization");
|
struct mg_str *v = mg_http_get_header(hm, "Authorization");
|
||||||
user[0] = pass[0] = '\0';
|
user[0] = pass[0] = '\0';
|
||||||
if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) {
|
if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int n = mg_base64_decode(v->ptr + 6, (int) v->len - 6, buf);
|
int n = mg_base64_decode(v->ptr + 6, (int) v->len - 6, buf);
|
||||||
const char *p = (const char *) memchr(buf, ':', n);
|
const char *p = (const char *) memchr(buf, ':', n > 0 ? (size_t) n : 0);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
snprintf(user, userlen, "%.*s", (int) (p - buf), buf);
|
snprintf(user, userlen, "%.*s", (int) (p - buf), buf);
|
||||||
snprintf(pass, passlen, "%.*s", n - (int) (p - buf) - 1, p + 1);
|
snprintf(pass, passlen, "%.*s", n - (int) (p - buf) - 1, p + 1);
|
||||||
@@ -736,20 +925,34 @@ void mg_http_creds(struct mg_http_message *hm, char *user, int userlen,
|
|||||||
} else if (v != NULL && v->len > 7 && memcmp(v->ptr, "Bearer ", 7) == 0) {
|
} else if (v != NULL && v->len > 7 && memcmp(v->ptr, "Bearer ", 7) == 0) {
|
||||||
snprintf(pass, passlen, "%.*s", (int) v->len - 7, v->ptr + 7);
|
snprintf(pass, passlen, "%.*s", (int) v->len - 7, v->ptr + 7);
|
||||||
} else if ((v = mg_http_get_header(hm, "Cookie")) != NULL) {
|
} else if ((v = mg_http_get_header(hm, "Cookie")) != NULL) {
|
||||||
size_t i;
|
struct mg_str t = mg_http_get_header_var(*v, mg_str_n("access_token", 12));
|
||||||
for (i = 0; i < v->len - 13; i++) {
|
if (t.len > 0) snprintf(pass, passlen, "%.*s", (int) t.len, t.ptr);
|
||||||
if (memcmp(&v->ptr[i], "access_token=", 13) == 0) {
|
|
||||||
const char *p2 = v->ptr + i + 13, *p3 = p2;
|
|
||||||
while (p2 < &v->ptr[v->len] && p2[0] != ';' && p2[0] != ' ') p2++;
|
|
||||||
snprintf(pass, passlen, "%.*s", (int) (p2 - p3), p3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
mg_http_get_var(&hm->query, "access_token", pass, passlen);
|
mg_http_get_var(&hm->query, "access_token", pass, passlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mg_str stripquotes(struct mg_str s) {
|
||||||
|
return s.len > 1 && s.ptr[0] == '"' && s.ptr[s.len - 1] == '"'
|
||||||
|
? mg_str_n(s.ptr + 1, s.len - 2)
|
||||||
|
: s;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i + v.len + 2 < s.len; i++) {
|
||||||
|
if (s.ptr[i + v.len] == '=' && memcmp(&s.ptr[i], v.ptr, v.len) == 0) {
|
||||||
|
const char *p = &s.ptr[i + v.len + 1], *b = p, *x = &s.ptr[s.len];
|
||||||
|
int q = p < x && *p == '"' ? 1 : 0;
|
||||||
|
while (p < x && (q ? p == b || *p != '"' : *p != ';' && *p != ' ')) p++;
|
||||||
|
// LOG(LL_INFO, ("[%.*s] [%.*s] [%.*s]", (int) s.len, s.ptr, (int) v.len,
|
||||||
|
// v.ptr, (int) (p - b), b));
|
||||||
|
return stripquotes(mg_str_n(b, (size_t)(p - b + q)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mg_str_n(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob) {
|
bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob) {
|
||||||
return mg_globmatch(glob, strlen(glob), hm->uri.ptr, hm->uri.len);
|
return mg_globmatch(glob, strlen(glob), hm->uri.ptr, hm->uri.len);
|
||||||
}
|
}
|
||||||
@@ -768,7 +971,7 @@ static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
|
|||||||
// Walk through all chunks in the chunked body. For each chunk, fire
|
// Walk through all chunks in the chunked body. For each chunk, fire
|
||||||
// an MG_EV_HTTP_CHUNK event.
|
// an MG_EV_HTTP_CHUNK event.
|
||||||
static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
||||||
int reqlen) {
|
size_t reqlen) {
|
||||||
size_t off = 0, bl, ll;
|
size_t off = 0, bl, ll;
|
||||||
while (off + reqlen < c->recv.len) {
|
while (off + reqlen < c->recv.len) {
|
||||||
char *buf = (char *) &c->recv.buf[reqlen];
|
char *buf = (char *) &c->recv.buf[reqlen];
|
||||||
@@ -784,15 +987,17 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
||||||
off = bl = 0;
|
off = bl = 0;
|
||||||
while (off + reqlen < c->recv.len) {
|
while (off + reqlen < c->recv.len) {
|
||||||
char *buf = (char *) &c->recv.buf[reqlen];
|
char *buf2 = (char *) &c->recv.buf[reqlen];
|
||||||
size_t memo = c->recv.len;
|
size_t memo2 = c->recv.len;
|
||||||
size_t cl = get_chunk_length(&buf[off], memo - reqlen - off, &ll);
|
size_t cl2 = get_chunk_length(&buf2[off], memo2 - reqlen - off, &ll);
|
||||||
size_t n = cl < ll + 2 ? 0 : cl - ll - 2;
|
size_t n = cl < ll + 2 ? 0 : cl2 - ll - 2;
|
||||||
if (cl <= 5) break;
|
memmove(buf2 + bl, buf2 + off + ll, n);
|
||||||
memmove(buf + bl, buf + off + ll, n);
|
|
||||||
bl += n;
|
bl += n;
|
||||||
off += cl;
|
off += cl2;
|
||||||
|
if (cl2 <= 5) break;
|
||||||
}
|
}
|
||||||
|
// LOG(LL_INFO, ("BL->%d del %d off %d", (int) bl, (int) del, (int) off));
|
||||||
|
c->recv.len -= off - bl;
|
||||||
// Set message length to indicate we've received
|
// Set message length to indicate we've received
|
||||||
// everything, to fire MG_EV_HTTP_MSG
|
// everything, to fire MG_EV_HTTP_MSG
|
||||||
hm->message.len = bl + reqlen;
|
hm->message.len = bl + reqlen;
|
||||||
@@ -817,8 +1022,10 @@ void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const char *end = &ch.ptr[ch.len];
|
const char *end = &ch.ptr[ch.len];
|
||||||
size_t n = end - (char *) c->recv.buf;
|
size_t n = (size_t)(end - (char *) c->recv.buf);
|
||||||
if (c->recv.len > n) memmove((char *) ch.ptr, end, c->recv.len - n);
|
if (c->recv.len > n) {
|
||||||
|
memmove((char *) ch.ptr, end, (size_t)(c->recv.len - n));
|
||||||
|
}
|
||||||
// LOG(LL_INFO, ("DELETING CHUNK: %zu %zu %zu\n%.*s", c->recv.len, n,
|
// LOG(LL_INFO, ("DELETING CHUNK: %zu %zu %zu\n%.*s", c->recv.len, n,
|
||||||
// ch.len, (int) ch.len, ch.ptr));
|
// ch.len, (int) ch.len, ch.ptr));
|
||||||
}
|
}
|
||||||
@@ -833,22 +1040,22 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
|||||||
bool is_chunked = n > 0 && mg_is_chunked(&hm);
|
bool is_chunked = n > 0 && mg_is_chunked(&hm);
|
||||||
if (ev == MG_EV_CLOSE) {
|
if (ev == MG_EV_CLOSE) {
|
||||||
hm.message.len = c->recv.len;
|
hm.message.len = c->recv.len;
|
||||||
hm.body.len = hm.message.len - (hm.body.ptr - hm.message.ptr);
|
hm.body.len = hm.message.len - (size_t)(hm.body.ptr - hm.message.ptr);
|
||||||
} else if (is_chunked) {
|
} else if (is_chunked && n > 0) {
|
||||||
walkchunks(c, &hm, n);
|
walkchunks(c, &hm, (size_t) n);
|
||||||
}
|
}
|
||||||
// LOG(LL_INFO,
|
// LOG(LL_INFO,
|
||||||
//("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len, c->recv.buf));
|
//("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len, c->recv.buf));
|
||||||
if (n < 0 && ev == MG_EV_READ) {
|
if (n < 0 && ev == MG_EV_READ) {
|
||||||
LOG(LL_ERROR, ("%lu HTTP parse error", c->id));
|
mg_error(c, "HTTP parse:\n%.*s", (int) c->recv.len, c->recv.buf);
|
||||||
c->is_closing = 1;
|
|
||||||
break;
|
break;
|
||||||
} else if (n > 0 && (size_t) c->recv.len >= hm.message.len) {
|
} else if (n > 0 && (size_t) c->recv.len >= hm.message.len) {
|
||||||
mg_call(c, MG_EV_HTTP_MSG, &hm);
|
mg_call(c, MG_EV_HTTP_MSG, &hm);
|
||||||
mg_iobuf_delete(&c->recv, hm.message.len);
|
mg_iobuf_delete(&c->recv, hm.message.len);
|
||||||
} else {
|
} else {
|
||||||
if (n > 0 && !is_chunked) {
|
if (n > 0 && !is_chunked) {
|
||||||
hm.chunk = mg_str_n((char *) &c->recv.buf[n], c->recv.len - n);
|
hm.chunk =
|
||||||
|
mg_str_n((char *) &c->recv.buf[n], c->recv.len - (size_t) n);
|
||||||
mg_call(c, MG_EV_HTTP_CHUNK, &hm);
|
mg_call(c, MG_EV_HTTP_CHUNK, &hm);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+15
-5
@@ -23,8 +23,16 @@ struct mg_http_message {
|
|||||||
|
|
||||||
// Parameter for mg_http_serve_dir()
|
// Parameter for mg_http_serve_dir()
|
||||||
struct mg_http_serve_opts {
|
struct mg_http_serve_opts {
|
||||||
const char *root_dir; // Web root directory, must be non-NULL
|
const char *root_dir; // Web root directory, must be non-NULL
|
||||||
const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml
|
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
|
||||||
|
const char *extra_headers; // Extra HTTP headers to add in responses
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameter for mg_http_next_multipart
|
||||||
|
struct mg_http_part {
|
||||||
|
struct mg_str name; // Form field name
|
||||||
|
struct mg_str filename; // Filename for file uploads
|
||||||
|
struct mg_str body; // Part contents
|
||||||
};
|
};
|
||||||
|
|
||||||
int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
|
int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
|
||||||
@@ -44,11 +52,13 @@ void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
|
|||||||
const char *body_fmt, ...);
|
const char *body_fmt, ...);
|
||||||
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
||||||
void mg_http_event_handler(struct mg_connection *c, int ev);
|
void mg_http_event_handler(struct mg_connection *c, int ev);
|
||||||
int mg_http_get_var(const struct mg_str *, const char *name, char *, int);
|
int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
|
||||||
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
||||||
int mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
||||||
void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int);
|
void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
|
||||||
bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
|
bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
|
||||||
int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
|
int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
|
||||||
const char *dir);
|
const char *dir);
|
||||||
void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
||||||
|
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
|
||||||
|
size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
|
||||||
+22
-7
@@ -3,18 +3,29 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
// Not using memset for zeroing memory, cause it can be dropped by compiler
|
||||||
|
// See https://github.com/cesanta/mongoose/pull/1265
|
||||||
|
static void zeromem(volatile unsigned char *buf, size_t len) {
|
||||||
|
if (buf != NULL) {
|
||||||
|
while (len--) *buf++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
|
int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
if (new_size == 0) {
|
if (new_size == 0) {
|
||||||
|
zeromem(io->buf, io->size);
|
||||||
free(io->buf);
|
free(io->buf);
|
||||||
io->buf = NULL;
|
io->buf = NULL;
|
||||||
io->len = io->size = 0;
|
io->len = io->size = 0;
|
||||||
} else if (new_size != io->size) {
|
} else if (new_size != io->size) {
|
||||||
// NOTE(lsm): do not use realloc here. Use malloc/free only, to ease the
|
// NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
|
||||||
// porting to some obscure platforms like FreeRTOS
|
// porting to some obscure platforms like FreeRTOS
|
||||||
void *p = malloc(new_size);
|
void *p = calloc(1, new_size);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
memcpy(p, io->buf, io->size < new_size ? io->size : new_size);
|
size_t len = new_size < io->len ? new_size : io->len;
|
||||||
|
if (len > 0) memcpy(p, io->buf, len);
|
||||||
|
zeromem(io->buf, io->size);
|
||||||
free(io->buf);
|
free(io->buf);
|
||||||
io->buf = (unsigned char *) p;
|
io->buf = (unsigned char *) p;
|
||||||
io->size = new_size;
|
io->size = new_size;
|
||||||
@@ -33,10 +44,13 @@ int mg_iobuf_init(struct mg_iobuf *io, size_t size) {
|
|||||||
|
|
||||||
size_t mg_iobuf_append(struct mg_iobuf *io, const void *buf, size_t len,
|
size_t mg_iobuf_append(struct mg_iobuf *io, const void *buf, size_t len,
|
||||||
size_t chunk_size) {
|
size_t chunk_size) {
|
||||||
size_t new_size = io->len + len + chunk_size;
|
size_t new_size = io->len + len;
|
||||||
new_size -= new_size % chunk_size;
|
if (new_size > io->size) {
|
||||||
if (new_size != io->size) mg_iobuf_resize(io, new_size);
|
new_size += chunk_size; // Make sure that io->size
|
||||||
if (new_size != io->size) len = 0; // Realloc failure, append nothing
|
new_size -= new_size % chunk_size; // is aligned by chunk_size boundary
|
||||||
|
mg_iobuf_resize(io, new_size); // Attempt to realloc
|
||||||
|
if (new_size != io->size) len = 0; // Realloc failure, append nothing
|
||||||
|
}
|
||||||
if (buf != NULL) memmove(io->buf + io->len, buf, len);
|
if (buf != NULL) memmove(io->buf + io->len, buf, len);
|
||||||
io->len += len;
|
io->len += len;
|
||||||
return len;
|
return len;
|
||||||
@@ -45,6 +59,7 @@ size_t mg_iobuf_append(struct mg_iobuf *io, const void *buf, size_t len,
|
|||||||
size_t mg_iobuf_delete(struct mg_iobuf *io, size_t len) {
|
size_t mg_iobuf_delete(struct mg_iobuf *io, size_t len) {
|
||||||
if (len > io->len) len = 0;
|
if (len > io->len) len = 0;
|
||||||
memmove(io->buf, io->buf + len, io->len - len);
|
memmove(io->buf, io->buf + len, io->len - len);
|
||||||
|
zeromem(io->buf + io->len - len, len);
|
||||||
io->len -= len;
|
io->len -= len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
#if MG_ENABLE_MGOS
|
#if MG_ENABLE_MGOS
|
||||||
#else
|
#else
|
||||||
#if MG_ENABLE_LOG
|
#if MG_ENABLE_LOG
|
||||||
static void mg_log_stdout(const void *buf, int len, void *userdata) {
|
static void mg_log_stdout(const void *buf, size_t len, void *userdata) {
|
||||||
(void) userdata;
|
(void) userdata;
|
||||||
fwrite(buf, 1, len, stdout);
|
fwrite(buf, 1, len, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *s_spec = "2";
|
static const char *s_spec = "2";
|
||||||
static void (*s_fn)(const void *, int, void *) = mg_log_stdout;
|
static void (*s_fn)(const void *, size_t, void *) = mg_log_stdout;
|
||||||
static void *s_fn_param = NULL;
|
static void *s_fn_param = NULL;
|
||||||
|
|
||||||
void mg_log_set(const char *spec) {
|
void mg_log_set(const char *spec) {
|
||||||
@@ -23,9 +23,12 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
|
|||||||
int max = LL_INFO;
|
int max = LL_INFO;
|
||||||
struct mg_str k, v, s = mg_str(s_spec);
|
struct mg_str k, v, s = mg_str(s_spec);
|
||||||
const char *p = strrchr(file, '/');
|
const char *p = strrchr(file, '/');
|
||||||
p = p == NULL ? file : p + 1;
|
|
||||||
|
|
||||||
if (s_fn == NULL) return false;
|
if (s_fn == NULL) return false;
|
||||||
|
|
||||||
|
if (p == NULL) p = strrchr(file, '\\');
|
||||||
|
p = p == NULL ? file : p + 1;
|
||||||
|
|
||||||
while (mg_next_comma_entry(&s, &k, &v)) {
|
while (mg_next_comma_entry(&s, &k, &v)) {
|
||||||
if (v.len == 0) max = atoi(k.ptr);
|
if (v.len == 0) max = atoi(k.ptr);
|
||||||
if (v.len > 0 && strncmp(p, k.ptr, k.len) == 0) max = atoi(v.ptr);
|
if (v.len > 0 && strncmp(p, k.ptr, k.len) == 0) max = atoi(v.ptr);
|
||||||
@@ -34,7 +37,7 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
|
|||||||
if (level <= max) {
|
if (level <= max) {
|
||||||
char timebuf[21], buf[50] = "";
|
char timebuf[21], buf[50] = "";
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm *tm = gmtime(&t);
|
struct tm tmp, *tm = gmtime_r(&t, &tmp);
|
||||||
int n, tag;
|
int n, tag;
|
||||||
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm);
|
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm);
|
||||||
tag = level == LL_ERROR ? 'E' : level == LL_INFO ? 'I' : ' ';
|
tag = level == LL_ERROR ? 'E' : level == LL_INFO ? 'I' : ' ';
|
||||||
@@ -56,14 +59,14 @@ void mg_log(const char *fmt, ...) {
|
|||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
s_fn(buf, len, s_fn_param);
|
s_fn(buf, len > 0 ? (size_t) len : 0, s_fn_param);
|
||||||
s_fn("\n", 1, s_fn_param);
|
s_fn("\n", 1, s_fn_param);
|
||||||
if (buf != mem) free(buf);
|
if (buf != mem) free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param) {
|
void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *fnd) {
|
||||||
s_fn = fn;
|
s_fn = fn;
|
||||||
s_fn_param = param;
|
s_fn_param = fnd;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -3,9 +3,6 @@
|
|||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#if MG_ENABLE_MGOS
|
|
||||||
#include <common/cs_dbg.h>
|
|
||||||
#else
|
|
||||||
#if MG_ENABLE_LOG
|
#if MG_ENABLE_LOG
|
||||||
#define LOG(level, args) \
|
#define LOG(level, args) \
|
||||||
do { \
|
do { \
|
||||||
@@ -15,8 +12,8 @@ enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG };
|
|||||||
bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
|
bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
|
||||||
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||||
void mg_log_set(const char *spec);
|
void mg_log_set(const char *spec);
|
||||||
void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param);
|
void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
|
||||||
#else
|
#else
|
||||||
#define LOG(level, args)
|
#define LOG(level, args) (void) 0
|
||||||
#endif
|
#define mg_log_set(x) (void) (x)
|
||||||
#endif
|
#endif
|
||||||
-197
@@ -1,197 +0,0 @@
|
|||||||
#include "dns.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "net.h"
|
|
||||||
#include "private.h"
|
|
||||||
#include "tls.h"
|
|
||||||
#include "url.h"
|
|
||||||
|
|
||||||
#if MG_ENABLE_LWIP
|
|
||||||
#include <lwip/tcp.h>
|
|
||||||
#include <lwip/udp.h>
|
|
||||||
|
|
||||||
static void tcp_error_cb(void *arg, err_t err) {
|
|
||||||
struct mg_connection *c = (struct mg_connection *) arg;
|
|
||||||
mg_error(c, "%p err %ld", c->fd, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static err_t connect_cb(void *arg, struct tcp_pcb *pcb, err_t err) {
|
|
||||||
struct mg_connection *c = (struct mg_connection *) arg;
|
|
||||||
LOG(LL_DEBUG, ("err %ld, arg %p, pcb %p", err, arg, pcb));
|
|
||||||
c->is_connecting = 0;
|
|
||||||
if (err != ERR_OK) mg_error(c, "%p err %d", c->fd, err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static err_t tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
|
|
||||||
err_t err) {
|
|
||||||
struct mg_connection *c = (struct mg_connection *) arg;
|
|
||||||
LOG(LL_DEBUG,
|
|
||||||
("err %ld, pbuf %p/%d, io.len %d, io.size %d", err, p,
|
|
||||||
p == NULL ? 0 : (int) p->len, (int) c->recv.len, (int) c->recv.size));
|
|
||||||
if (err == ERR_OK && p != NULL) {
|
|
||||||
#if 0
|
|
||||||
if (s->io.size < s->io.len + p->len) {
|
|
||||||
char *buf = realloc(s->io.buf, s->io.len + p->len);
|
|
||||||
if (buf != NULL) {
|
|
||||||
s->io.buf = buf;
|
|
||||||
s->io.size = s->io.len + p->len;
|
|
||||||
} else {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// MLOG(LL_DEBUG, " --> cpy, %p %p", s->io.buf, p->payload);
|
|
||||||
memcpy(s->io.buf + s->io.len, p->payload, p->len);
|
|
||||||
s->io.len += p->len;
|
|
||||||
#endif
|
|
||||||
tcp_recved(pcb, p->len);
|
|
||||||
pbuf_free(p);
|
|
||||||
return err;
|
|
||||||
} else {
|
|
||||||
// rmsock(s);
|
|
||||||
return ERR_ABRT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|
||||||
const ip_addr_t *addr, uint16_t port) {
|
|
||||||
LOG(LL_DEBUG,
|
|
||||||
("%p %p pbuf %p/%d port %hu", arg, pcb, p, p == NULL ? 0 : p->len, port));
|
|
||||||
}
|
|
||||||
|
|
||||||
static err_t tcp_sent_cb(void *arg, struct tcp_pcb *pcb, uint16_t len) {
|
|
||||||
LOG(LL_DEBUG, ("%p %d", pcb, (int) len));
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static int ll_write(struct mg_connection *c, const void *buf, int len,
|
|
||||||
int *fail) {
|
|
||||||
int n = c->is_tls ? mg_tls_send(c, buf, len, fail)
|
|
||||||
: mg_sock_send(c, buf, len, fail);
|
|
||||||
LOG(*fail ? LL_ERROR : LL_VERBOSE_DEBUG,
|
|
||||||
("%p %c%c%c %d/%d %d", c->fd, c->is_tls ? 'T' : 't',
|
|
||||||
c->is_udp ? 'U' : 'u', c->is_connecting ? 'C' : 'c', n, len,
|
|
||||||
MG_SOCK_ERRNO));
|
|
||||||
if (n > 0 && c->is_hexdumping) mg_hexdump(c, "->", buf, n);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
|
||||||
if (c->is_udp) {
|
|
||||||
struct udp_pcb *pcb = (struct udp_pcb *) c->fd;
|
|
||||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
|
|
||||||
if (p != NULL) {
|
|
||||||
// p->payload = (void *) buf;
|
|
||||||
memcpy(p->payload, buf, len);
|
|
||||||
err_t err = udp_send(pcb, p);
|
|
||||||
pbuf_free(p);
|
|
||||||
LOG(LL_DEBUG,
|
|
||||||
("%lu UDP %d bytes -> %x:%hu, err %ld", c->id, (int) len,
|
|
||||||
(unsigned) *(uint32_t *) &pcb->remote_ip, pcb->remote_port, err));
|
|
||||||
if (err != ERR_OK) mg_error(c, "%p err %d", c->fd, err);
|
|
||||||
} else {
|
|
||||||
mg_error(c, "%p pbuf OOM", c->fd);
|
|
||||||
}
|
|
||||||
} else if (c->is_connecting) {
|
|
||||||
mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
int fail, n = c->is_udp
|
|
||||||
? ll_write(c, buf, (SOCKET) len, &fail)
|
|
||||||
: mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
|
|
||||||
return n;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mg_connection *mg_mkconn(const char *url) {
|
|
||||||
struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c));
|
|
||||||
typedef void *(*new_t)(void);
|
|
||||||
int is_udp = strncmp(url, "udp:", 4) == 0;
|
|
||||||
if (c == NULL) {
|
|
||||||
LOG(LL_ERROR, ("%s %s", url, "OOM"));
|
|
||||||
} else if ((c->fd = (is_udp ? (new_t) udp_new : (new_t) tcp_new)()) == NULL) {
|
|
||||||
LOG(LL_ERROR, ("%s new", url));
|
|
||||||
free(c);
|
|
||||||
c = NULL;
|
|
||||||
} else {
|
|
||||||
c->is_udp = is_udp;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
|
||||||
mg_event_handler_t fn, void *fn_data) {
|
|
||||||
struct mg_connection *c = mg_mkconn(url);
|
|
||||||
struct mg_str host = mg_url_host(url);
|
|
||||||
if (c == NULL) return c;
|
|
||||||
c->next = mgr->conns;
|
|
||||||
mgr->conns = c;
|
|
||||||
// mg_set_non_blocking_mode((SOCKET) c->fd);
|
|
||||||
c->is_client = 1;
|
|
||||||
c->peer.port = mg_htons(mg_url_port(url));
|
|
||||||
c->fn = fn;
|
|
||||||
c->fn_data = fn_data;
|
|
||||||
c->is_hexdumping = 1;
|
|
||||||
if (c->is_udp) {
|
|
||||||
udp_bind(c->fd, IP_ADDR_ANY, 0);
|
|
||||||
udp_recv(c->fd, udp_recv_cb, c);
|
|
||||||
} else {
|
|
||||||
tcp_arg(c->fd, c);
|
|
||||||
tcp_err(c->fd, tcp_error_cb);
|
|
||||||
tcp_sent(c->fd, tcp_sent_cb);
|
|
||||||
tcp_recv(c->fd, tcp_recv_cb);
|
|
||||||
tcp_bind(c->fd, IP_ADDR_ANY, 0);
|
|
||||||
tcp_nagle_disable((struct tcp_pcb *) c->fd);
|
|
||||||
}
|
|
||||||
LOG(LL_DEBUG, ("%lu -> %s %s", c->id, url, c->is_udp ? "UDP" : "TCP"));
|
|
||||||
mg_resolve(mgr, c, &host, mgr->dnstimeout);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_connect_resolved(struct mg_connection *c) {
|
|
||||||
char buf[40];
|
|
||||||
ip_addr_t ipaddr;
|
|
||||||
memcpy(&ipaddr, &c->peer.ip, sizeof(ipaddr));
|
|
||||||
mg_call(c, MG_EV_RESOLVE, NULL);
|
|
||||||
LOG(LL_DEBUG, ("%lu resolved to %s", c->id, mg_straddr(c, buf, sizeof(buf))));
|
|
||||||
err_t err = c->is_udp ? udp_connect((struct udp_pcb *) c->fd, &ipaddr,
|
|
||||||
mg_ntohs(c->peer.port))
|
|
||||||
: tcp_connect((struct tcp_pcb *) c->fd, &ipaddr,
|
|
||||||
mg_ntohs(c->peer.port), connect_cb);
|
|
||||||
if (c->is_udp) c->is_connecting = 0;
|
|
||||||
if (err != ERR_OK) mg_error(c, "%p failed, err %d", c->fd, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static err_t accept_cb(void *arg, struct tcp_pcb *pcb, err_t e) {
|
|
||||||
LOG(LL_DEBUG, ("%p err %ld, pcb %p", arg, e, pcb));
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
|
||||||
mg_event_handler_t fn, void *fn_data) {
|
|
||||||
struct mg_connection *c = mg_mkconn(url);
|
|
||||||
struct mg_str host = mg_url_host(url);
|
|
||||||
uint16_t port = mg_url_port(url);
|
|
||||||
uint32_t ipaddr;
|
|
||||||
err_t err;
|
|
||||||
if (c == NULL) return c;
|
|
||||||
mg_aton(host.ptr, &ipaddr);
|
|
||||||
if (!mg_vcasecmp(&host, "localhost")) ipaddr = mg_htonl(0x7f000001);
|
|
||||||
if ((err = tcp_bind(c->fd, (ip_addr_t *) &ipaddr, port)) != ERR_OK) {
|
|
||||||
mg_error(c, "%p tcp_bind(%x:%hu) -> %ld", c->fd, ipaddr, port, err);
|
|
||||||
} else {
|
|
||||||
tcp_listen(c->fd);
|
|
||||||
tcp_accept(c->fd, accept_cb);
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
|
||||||
LOG(LL_DEBUG, ("%p %d", mgr, ms));
|
|
||||||
mg_usleep(200 * 1000);
|
|
||||||
mg_timer_poll(mg_millis());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
+29
-28
@@ -1,8 +1,8 @@
|
|||||||
|
#include "mqtt.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mqtt.h"
|
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -20,14 +20,14 @@ enum { MQTT_OK, MQTT_INCOMPLETE, MQTT_MALFORMED };
|
|||||||
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
|
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
|
||||||
uint32_t len) {
|
uint32_t len) {
|
||||||
uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
|
uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
|
||||||
buf[0] = (cmd << 4) | flags;
|
buf[0] = (uint8_t)((cmd << 4) | flags);
|
||||||
do {
|
do {
|
||||||
*vlen = len % 0x80;
|
*vlen = len % 0x80;
|
||||||
len /= 0x80;
|
len /= 0x80;
|
||||||
if (len > 0) *vlen |= 0x80;
|
if (len > 0) *vlen |= 0x80;
|
||||||
vlen++;
|
vlen++;
|
||||||
} while (len > 0 && vlen < &buf[sizeof(buf)]);
|
} while (len > 0 && vlen < &buf[sizeof(buf)]);
|
||||||
mg_send(c, buf, vlen - buf);
|
mg_send(c, buf, (size_t)(vlen - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_send_u16(struct mg_connection *c, uint16_t value) {
|
static void mg_send_u16(struct mg_connection *c, uint16_t value) {
|
||||||
@@ -37,7 +37,7 @@ static void mg_send_u16(struct mg_connection *c, uint16_t value) {
|
|||||||
static void mqtt_login(struct mg_connection *c, const char *url,
|
static void mqtt_login(struct mg_connection *c, const char *url,
|
||||||
struct mg_mqtt_opts *opts) {
|
struct mg_mqtt_opts *opts) {
|
||||||
uint32_t total_len = 7 + 1 + 2 + 2;
|
uint32_t total_len = 7 + 1 + 2 + 2;
|
||||||
uint16_t flags = (opts->qos & 3) << 3;
|
uint16_t flags = (uint16_t)(((uint16_t) opts->qos & 3) << 3);
|
||||||
struct mg_str user = mg_url_user(url);
|
struct mg_str user = mg_url_user(url);
|
||||||
struct mg_str pass = mg_url_pass(url);
|
struct mg_str pass = mg_url_pass(url);
|
||||||
|
|
||||||
@@ -82,8 +82,8 @@ static void mqtt_login(struct mg_connection *c, const char *url,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
|
void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
|
||||||
struct mg_str *data) {
|
struct mg_str *data, int qos, bool retain) {
|
||||||
uint8_t flags = MQTT_QOS(1);
|
uint8_t flags = (uint8_t)(((qos & 3) << 1) | (retain ? 1 : 0));
|
||||||
uint32_t total_len = 2 + (uint32_t) topic->len + (uint32_t) data->len;
|
uint32_t total_len = 2 + (uint32_t) topic->len + (uint32_t) data->len;
|
||||||
LOG(LL_DEBUG, ("%lu [%.*s] -> [%.*s]", c->id, (int) topic->len,
|
LOG(LL_DEBUG, ("%lu [%.*s] -> [%.*s]", c->id, (int) topic->len,
|
||||||
(char *) topic->ptr, (int) data->len, (char *) data->ptr));
|
(char *) topic->ptr, (int) data->len, (char *) data->ptr));
|
||||||
@@ -99,17 +99,17 @@ void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
|
|||||||
mg_send(c, data->ptr, data->len);
|
mg_send(c, data->ptr, data->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_mqtt_sub(struct mg_connection *c, struct mg_str *topic) {
|
void mg_mqtt_sub(struct mg_connection *c, struct mg_str *topic, int qos) {
|
||||||
static uint16_t s_id;
|
static uint16_t s_id;
|
||||||
uint8_t qos = 1;
|
uint8_t qos_ = qos & 3;
|
||||||
uint32_t total_len = 2 + (uint32_t) topic->len + 2 + 1;
|
uint32_t total_len = 2 + (uint32_t) topic->len + 2 + 1;
|
||||||
mg_mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, (uint8_t) MQTT_QOS(qos),
|
mg_mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, (uint8_t) MQTT_QOS(qos_),
|
||||||
total_len);
|
total_len);
|
||||||
if (++s_id == 0) ++s_id;
|
if (++s_id == 0) ++s_id;
|
||||||
mg_send_u16(c, mg_htons(s_id));
|
mg_send_u16(c, mg_htons(s_id));
|
||||||
mg_send_u16(c, mg_htons((uint16_t) topic->len));
|
mg_send_u16(c, mg_htons((uint16_t) topic->len));
|
||||||
mg_send(c, topic->ptr, topic->len);
|
mg_send(c, topic->ptr, topic->len);
|
||||||
mg_send(c, &qos, sizeof(qos));
|
mg_send(c, &qos_, sizeof(qos_));
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
|
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
|
||||||
@@ -119,21 +119,21 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
|
|||||||
memset(m, 0, sizeof(*m));
|
memset(m, 0, sizeof(*m));
|
||||||
m->dgram.ptr = (char *) buf;
|
m->dgram.ptr = (char *) buf;
|
||||||
if (len < 2) return MQTT_INCOMPLETE;
|
if (len < 2) return MQTT_INCOMPLETE;
|
||||||
m->cmd = buf[0] >> 4;
|
m->cmd = (uint8_t)(buf[0] >> 4);
|
||||||
m->qos = (buf[0] >> 1) & 3;
|
m->qos = (buf[0] >> 1) & 3;
|
||||||
|
|
||||||
n = len_len = 0;
|
n = len_len = 0;
|
||||||
p = (uint8_t *) buf + 1;
|
p = (uint8_t *) buf + 1;
|
||||||
while ((size_t)(p - buf) < len) {
|
while ((size_t)(p - buf) < len) {
|
||||||
lc = *((uint8_t *) p++);
|
lc = *((uint8_t *) p++);
|
||||||
n += (lc & 0x7f) << 7 * len_len;
|
n += (uint32_t)((lc & 0x7f) << 7 * len_len);
|
||||||
len_len++;
|
len_len++;
|
||||||
if (!(lc & 0x80)) break;
|
if (!(lc & 0x80)) break;
|
||||||
if (len_len >= 4) return MQTT_MALFORMED;
|
if (len_len >= 4) return MQTT_MALFORMED;
|
||||||
}
|
}
|
||||||
end = p + n;
|
end = p + n;
|
||||||
if (lc & 0x80 || end > buf + len) return MQTT_INCOMPLETE;
|
if (lc & 0x80 || end > buf + len) return MQTT_INCOMPLETE;
|
||||||
m->dgram.len = end - buf;
|
m->dgram.len = (size_t)(end - buf);
|
||||||
|
|
||||||
switch (m->cmd) {
|
switch (m->cmd) {
|
||||||
case MQTT_CMD_CONNACK:
|
case MQTT_CMD_CONNACK:
|
||||||
@@ -146,28 +146,28 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
|
|||||||
case MQTT_CMD_PUBCOMP:
|
case MQTT_CMD_PUBCOMP:
|
||||||
case MQTT_CMD_SUBACK:
|
case MQTT_CMD_SUBACK:
|
||||||
if (p + 2 > end) return MQTT_MALFORMED;
|
if (p + 2 > end) return MQTT_MALFORMED;
|
||||||
m->id = (p[0] << 8) | p[1];
|
m->id = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
|
||||||
break;
|
break;
|
||||||
case MQTT_CMD_SUBSCRIBE: {
|
case MQTT_CMD_SUBSCRIBE: {
|
||||||
if (p + 2 > end) return MQTT_MALFORMED;
|
if (p + 2 > end) return MQTT_MALFORMED;
|
||||||
m->id = (p[0] << 8) | p[1];
|
m->id = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
|
||||||
p += 2;
|
p += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MQTT_CMD_PUBLISH: {
|
case MQTT_CMD_PUBLISH: {
|
||||||
if (p + 2 > end) return MQTT_MALFORMED;
|
if (p + 2 > end) return MQTT_MALFORMED;
|
||||||
m->topic.len = (p[0] << 8) | p[1];
|
m->topic.len = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
|
||||||
m->topic.ptr = (char *) p + 2;
|
m->topic.ptr = (char *) p + 2;
|
||||||
p += 2 + m->topic.len;
|
p += 2 + m->topic.len;
|
||||||
if (p > end) return MQTT_MALFORMED;
|
if (p > end) return MQTT_MALFORMED;
|
||||||
if (m->qos > 0) {
|
if (m->qos > 0) {
|
||||||
if (p + 2 > end) return MQTT_MALFORMED;
|
if (p + 2 > end) return MQTT_MALFORMED;
|
||||||
m->id = (p[0] << 8) | p[1];
|
m->id = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
if (p > end) return MQTT_MALFORMED;
|
if (p > end) return MQTT_MALFORMED;
|
||||||
m->data.ptr = (char *) p;
|
m->data.ptr = (char *) p;
|
||||||
m->data.len = end - p;
|
m->data.len = (size_t)(end - p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -176,28 +176,29 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
|
|||||||
return MQTT_OK;
|
return MQTT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_mqtt_next_topic(struct mg_mqtt_message *msg, struct mg_str *topic,
|
static size_t mg_mqtt_next_topic(struct mg_mqtt_message *msg,
|
||||||
uint8_t *qos, int pos) {
|
struct mg_str *topic, uint8_t *qos,
|
||||||
|
size_t pos) {
|
||||||
unsigned char *buf = (unsigned char *) msg->dgram.ptr + pos;
|
unsigned char *buf = (unsigned char *) msg->dgram.ptr + pos;
|
||||||
int new_pos;
|
size_t new_pos;
|
||||||
if ((size_t) pos >= msg->dgram.len) return -1;
|
if (pos >= msg->dgram.len) return 0;
|
||||||
|
|
||||||
topic->len = buf[0] << 8 | buf[1];
|
topic->len = (size_t)(((unsigned) buf[0]) << 8 | buf[1]);
|
||||||
topic->ptr = (char *) buf + 2;
|
topic->ptr = (char *) buf + 2;
|
||||||
new_pos = pos + 2 + topic->len + (qos == NULL ? 0 : 1);
|
new_pos = pos + 2 + topic->len + (qos == NULL ? 0 : 1);
|
||||||
if ((size_t) new_pos > msg->dgram.len) return -1;
|
if ((size_t) new_pos > msg->dgram.len) return 0;
|
||||||
if (qos != NULL) *qos = buf[2 + topic->len];
|
if (qos != NULL) *qos = buf[2 + topic->len];
|
||||||
return new_pos;
|
return new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||||
uint8_t *qos, int pos) {
|
uint8_t *qos, size_t pos) {
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
return mg_mqtt_next_topic(msg, topic, qos == NULL ? &tmp : qos, pos);
|
return mg_mqtt_next_topic(msg, topic, qos == NULL ? &tmp : qos, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||||
int pos) {
|
size_t pos) {
|
||||||
return mg_mqtt_next_topic(msg, topic, NULL, pos);
|
return mg_mqtt_next_topic(msg, topic, NULL, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -33,9 +33,9 @@ struct mg_mqtt_opts {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mg_mqtt_message {
|
struct mg_mqtt_message {
|
||||||
struct mg_str topic; // Parsed topic
|
struct mg_str topic; // Parsed topic
|
||||||
struct mg_str data; // Parsed message
|
struct mg_str data; // Parsed message
|
||||||
struct mg_str dgram; // Whole MQTT datagram, including headers
|
struct mg_str dgram; // Whole MQTT datagram, including headers
|
||||||
uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
|
uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
|
||||||
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
|
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
|
||||||
uint8_t qos; // Quality of service
|
uint8_t qos; // Quality of service
|
||||||
@@ -47,16 +47,16 @@ struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url,
|
|||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
void mg_mqtt_pub(struct mg_connection *, struct mg_str *topic,
|
void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
|
||||||
struct mg_str *data);
|
struct mg_str *data, int qos, bool retain);
|
||||||
void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic);
|
void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic, int qos);
|
||||||
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
|
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
|
||||||
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
|
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||||
uint8_t *qos, int pos);
|
uint8_t *qos, size_t pos);
|
||||||
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
|
||||||
int pos);
|
size_t pos);
|
||||||
void mg_mqtt_ping(struct mg_connection *);
|
void mg_mqtt_ping(struct mg_connection *);
|
||||||
void mg_mqtt_pong(struct mg_connection *);
|
void mg_mqtt_pong(struct mg_connection *);
|
||||||
void mg_mqtt_disconnect(struct mg_connection *);
|
void mg_mqtt_disconnect(struct mg_connection *);
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "log.h"
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||||
char mem[256], *buf = mem;
|
char mem[256], *buf = mem;
|
||||||
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||||
len = mg_send(c, buf, len);
|
len = mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||||
if (buf != mem) free(buf);
|
if (buf != mem) free(buf);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
|
|||||||
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
||||||
int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
|
int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
|
||||||
if (octet > 255) return false;
|
if (octet > 255) return false;
|
||||||
data[num_dots] = octet;
|
data[num_dots] = (uint8_t) octet;
|
||||||
} else if (str.ptr[i] == '.') {
|
} else if (str.ptr[i] == '.') {
|
||||||
if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
|
if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
|
||||||
num_dots++;
|
num_dots++;
|
||||||
@@ -115,24 +115,25 @@ void mg_mgr_free(struct mg_mgr *mgr) {
|
|||||||
struct mg_connection *c;
|
struct mg_connection *c;
|
||||||
for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
|
for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
|
||||||
mg_mgr_poll(mgr, 0);
|
mg_mgr_poll(mgr, 0);
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
FreeRTOS_DeleteSocketSet(mgr->ss);
|
FreeRTOS_DeleteSocketSet(mgr->ss);
|
||||||
#endif
|
#endif
|
||||||
LOG(LL_INFO, ("All connections closed"));
|
LOG(LL_INFO, ("All connections closed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_mgr_init(struct mg_mgr *mgr) {
|
void mg_mgr_init(struct mg_mgr *mgr) {
|
||||||
#ifdef _WIN32
|
memset(mgr, 0, sizeof(*mgr));
|
||||||
WSADATA data;
|
#if defined(_WIN32) && MG_ENABLE_WINSOCK
|
||||||
WSAStartup(MAKEWORD(2, 2), &data);
|
// clang-format off
|
||||||
#elif MG_ARCH == MG_ARCH_FREERTOS
|
{ WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
|
||||||
|
// clang-format on
|
||||||
|
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
mgr->ss = FreeRTOS_CreateSocketSet();
|
mgr->ss = FreeRTOS_CreateSocketSet();
|
||||||
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
|
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
|
||||||
// Ignore SIGPIPE signal, so if client cancels the request, it
|
// Ignore SIGPIPE signal, so if client cancels the request, it
|
||||||
// won't kill the whole process.
|
// won't kill the whole process.
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
memset(mgr, 0, sizeof(*mgr));
|
|
||||||
mgr->dnstimeout = 3000;
|
mgr->dnstimeout = 3000;
|
||||||
mgr->dns4.url = "udp://8.8.8.8:53";
|
mgr->dns4.url = "udp://8.8.8.8:53";
|
||||||
mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
|
mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct mg_mgr {
|
|||||||
int dnstimeout; // DNS resolve timeout in milliseconds
|
int dnstimeout; // DNS resolve timeout in milliseconds
|
||||||
unsigned long nextid; // Next connection ID
|
unsigned long nextid; // Next connection ID
|
||||||
void *userdata; // Arbitrary user data pointer
|
void *userdata; // Arbitrary user data pointer
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
SocketSet_t ss; // NOTE(lsm): referenced from socket struct
|
SocketSet_t ss; // NOTE(lsm): referenced from socket struct
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -32,13 +32,13 @@ struct mg_mgr {
|
|||||||
struct mg_connection {
|
struct mg_connection {
|
||||||
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
||||||
struct mg_mgr *mgr; // Our container
|
struct mg_mgr *mgr; // Our container
|
||||||
struct mg_addr peer; // Remote peer address
|
struct mg_addr peer; // Remote address. For listeners, local address
|
||||||
void *fd; // Connected socket, or LWIP data
|
void *fd; // Connected socket, or LWIP data
|
||||||
unsigned long id; // Auto-incrementing unique connection ID
|
unsigned long id; // Auto-incrementing unique connection ID
|
||||||
struct mg_iobuf recv; // Incoming data
|
struct mg_iobuf recv; // Incoming data
|
||||||
struct mg_iobuf send; // Outgoing data
|
struct mg_iobuf send; // Outgoing data
|
||||||
mg_event_handler_t fn; // User-specified event handler function
|
mg_event_handler_t fn; // User-specified event handler function
|
||||||
void *fn_data; // User-speficied function parameter
|
void *fn_data; // User-specified function parameter
|
||||||
mg_event_handler_t pfn; // Protocol-specific handler function
|
mg_event_handler_t pfn; // Protocol-specific handler function
|
||||||
void *pfn_data; // Protocol-specific function parameter
|
void *pfn_data; // Protocol-specific function parameter
|
||||||
char label[50]; // Arbitrary label
|
char label[50]; // Arbitrary label
|
||||||
@@ -46,7 +46,7 @@ struct mg_connection {
|
|||||||
unsigned is_listening : 1; // Listening connection
|
unsigned is_listening : 1; // Listening connection
|
||||||
unsigned is_client : 1; // Outbound (client) connection
|
unsigned is_client : 1; // Outbound (client) connection
|
||||||
unsigned is_accepted : 1; // Accepted (server) connection
|
unsigned is_accepted : 1; // Accepted (server) connection
|
||||||
unsigned is_resolving : 1; // Non-blocking DNS resolv is in progress
|
unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
|
||||||
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
||||||
unsigned is_tls : 1; // TLS-enabled connection
|
unsigned is_tls : 1; // TLS-enabled connection
|
||||||
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
||||||
@@ -67,7 +67,7 @@ struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
|
|||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
||||||
mg_event_handler_t fn, void *fn_data);
|
mg_event_handler_t fn, void *fn_data);
|
||||||
int mg_send(struct mg_connection *, const void *, size_t);
|
bool mg_send(struct mg_connection *, const void *, size_t);
|
||||||
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||||||
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||||||
char *mg_straddr(struct mg_connection *, char *, size_t);
|
char *mg_straddr(struct mg_connection *, char *, size_t);
|
||||||
|
|||||||
@@ -1,12 +1 @@
|
|||||||
void mg_connect_resolved(struct mg_connection *);
|
void mg_connect_resolved(struct mg_connection *);
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
|
||||||
static inline void *mg_calloc(int cnt, size_t size) {
|
|
||||||
void *p = pvPortMalloc(size);
|
|
||||||
if (p != NULL) memset(p, 0, size);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
#define calloc(a, b) mg_calloc((a), (b))
|
|
||||||
#define malloc(a) pvPortMalloc(a)
|
|
||||||
#define free(a) vPortFree(a)
|
|
||||||
#endif
|
|
||||||
+3
-3
@@ -22,8 +22,8 @@ int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
|
|||||||
} else {
|
} else {
|
||||||
uint32_t *data = (uint32_t *) &buf[40];
|
uint32_t *data = (uint32_t *) &buf[40];
|
||||||
tv->tv_sec = mg_ntohl(data[0]) - SNTP_TIME_OFFSET;
|
tv->tv_sec = mg_ntohl(data[0]) - SNTP_TIME_OFFSET;
|
||||||
tv->tv_usec = mg_ntohl(data[1]);
|
tv->tv_usec = (suseconds_t) mg_ntohl(data[1]);
|
||||||
s_sntmp_next = tv->tv_sec + SNTP_INTERVAL_SEC;
|
s_sntmp_next = (unsigned long) (tv->tv_sec + SNTP_INTERVAL_SEC);
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@@ -39,7 +39,7 @@ static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
|||||||
}
|
}
|
||||||
c->recv.len = 0; // Clear receive buffer
|
c->recv.len = 0; // Clear receive buffer
|
||||||
} else if (ev == MG_EV_RESOLVE) {
|
} else if (ev == MG_EV_RESOLVE) {
|
||||||
mg_sntp_send(c, time(NULL));
|
mg_sntp_send(c, (unsigned long) time(NULL));
|
||||||
} else if (ev == MG_EV_CLOSE) {
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
// mg_fn_del(c, sntp_cb);
|
// mg_fn_del(c, sntp_cb);
|
||||||
}
|
}
|
||||||
|
|||||||
+165
-147
@@ -10,25 +10,41 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#if MG_ENABLE_SOCKET
|
#if MG_ENABLE_SOCKET
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && MG_ENABLE_WINSOCK
|
||||||
#define MG_SOCK_ERRNO WSAGetLastError()
|
#define MG_SOCK_ERRNO WSAGetLastError()
|
||||||
#define FD(C_) ((SOCKET)(C_)->fd)
|
|
||||||
#ifndef SO_EXCLUSIVEADDRUSE
|
#ifndef SO_EXCLUSIVEADDRUSE
|
||||||
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
|
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
|
||||||
#endif
|
#endif
|
||||||
#elif MG_ARCH == MG_ARCH_FREERTOS
|
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
#define MG_SOCK_ERRNO errno
|
#define MG_SOCK_ERRNO errno
|
||||||
typedef Socket_t SOCKET;
|
typedef Socket_t SOCKET;
|
||||||
#define FD(C_) ((long) (C_)->fd)
|
|
||||||
#define INVALID_SOCKET FREERTOS_INVALID_SOCKET
|
#define INVALID_SOCKET FREERTOS_INVALID_SOCKET
|
||||||
#else
|
#else
|
||||||
#define MG_SOCK_ERRNO errno
|
#define MG_SOCK_ERRNO errno
|
||||||
|
#ifndef closesocket
|
||||||
#define closesocket(x) close(x)
|
#define closesocket(x) close(x)
|
||||||
|
#endif
|
||||||
#define INVALID_SOCKET (-1)
|
#define INVALID_SOCKET (-1)
|
||||||
typedef int SOCKET;
|
typedef int SOCKET;
|
||||||
#define FD(C_) ((SOCKET)(long) (C_)->fd)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
union _su {
|
||||||
|
SOCKET s;
|
||||||
|
void *ptr;
|
||||||
|
};
|
||||||
|
#define FD(c_) ptr2sock((c_)->fd)
|
||||||
|
|
||||||
|
static SOCKET ptr2sock(void *ptr) {
|
||||||
|
union _su u = {0};
|
||||||
|
u.ptr = ptr;
|
||||||
|
return u.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *sock2ptr(SOCKET s) {
|
||||||
|
union _su u = {s};
|
||||||
|
return u.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef MSG_NONBLOCKING
|
#ifndef MSG_NONBLOCKING
|
||||||
#define MSG_NONBLOCKING 0
|
#define MSG_NONBLOCKING 0
|
||||||
#endif
|
#endif
|
||||||
@@ -57,61 +73,32 @@ static union usa tousa(struct mg_addr *a) {
|
|||||||
return usa;
|
return usa;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_sock_failed(void) {
|
static bool mg_sock_would_block(void) {
|
||||||
int err = MG_SOCK_ERRNO;
|
int err = MG_SOCK_ERRNO;
|
||||||
return err != EINPROGRESS && err != EWOULDBLOCK
|
return err == EINPROGRESS || err == EWOULDBLOCK
|
||||||
#ifndef WINCE
|
#ifndef WINCE
|
||||||
&& err != EAGAIN && err != EINTR
|
|| err == EAGAIN || err == EINTR
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) && MG_ENABLE_WINSOCK
|
||||||
&& err != WSAEINTR && err != WSAEWOULDBLOCK
|
|| err == WSAEINTR || err == WSAEWOULDBLOCK
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mg_connection *alloc_conn(struct mg_mgr *mgr, int is_client,
|
static struct mg_connection *alloc_conn(struct mg_mgr *mgr, bool is_client,
|
||||||
SOCKET fd) {
|
SOCKET fd) {
|
||||||
struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c));
|
struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c));
|
||||||
if (c != NULL) {
|
if (c != NULL) {
|
||||||
c->is_client = is_client;
|
c->is_client = is_client;
|
||||||
c->fd = (void *) (long) fd;
|
c->fd = sock2ptr(fd);
|
||||||
c->mgr = mgr;
|
c->mgr = mgr;
|
||||||
c->id = ++mgr->nextid;
|
c->id = ++mgr->nextid;
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_sock_recv(struct mg_connection *c, void *buf, int len,
|
static long mg_sock_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
int *fail) {
|
long n = 0;
|
||||||
int n = 0;
|
|
||||||
if (c->is_udp) {
|
|
||||||
union usa usa;
|
|
||||||
socklen_t slen = sizeof(usa.sin);
|
|
||||||
#if MG_ENABLE_IPV6
|
|
||||||
if (c->peer.is_ip6) slen = sizeof(usa.sin6);
|
|
||||||
#endif
|
|
||||||
n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
|
|
||||||
if (n > 0) {
|
|
||||||
if (c->peer.is_ip6) {
|
|
||||||
#if MG_ENABLE_IPV6
|
|
||||||
memcpy(c->peer.ip6, &usa.sin6.sin6_addr, sizeof(c->peer.ip6));
|
|
||||||
c->peer.port = usa.sin6.sin6_port;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
c->peer.ip = *(uint32_t *) &usa.sin.sin_addr;
|
|
||||||
c->peer.port = usa.sin.sin_port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
|
|
||||||
}
|
|
||||||
*fail = (n == 0) || (n < 0 && mg_sock_failed());
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mg_sock_send(struct mg_connection *c, const void *buf, int len,
|
|
||||||
int *fail) {
|
|
||||||
int n = 0;
|
|
||||||
if (c->is_udp) {
|
if (c->is_udp) {
|
||||||
union usa usa = tousa(&c->peer);
|
union usa usa = tousa(&c->peer);
|
||||||
socklen_t slen = sizeof(usa.sin);
|
socklen_t slen = sizeof(usa.sin);
|
||||||
@@ -122,78 +109,41 @@ static int mg_sock_send(struct mg_connection *c, const void *buf, int len,
|
|||||||
} else {
|
} else {
|
||||||
n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
|
n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
|
||||||
}
|
}
|
||||||
*fail = (n == 0) || (n < 0 && mg_sock_failed());
|
return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ll_read(struct mg_connection *c, void *buf, int len, int *fail) {
|
bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
int n = c->is_tls ? mg_tls_recv(c, buf, len, fail)
|
return c->is_udp ? mg_sock_send(c, buf, len) > 0
|
||||||
: mg_sock_recv(c, buf, len, fail);
|
: mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
|
||||||
LOG(*fail ? LL_DEBUG : LL_VERBOSE_DEBUG,
|
|
||||||
("%lu %c%c%c %d/%d %d %d", c->id, c->is_tls ? 'T' : 't',
|
|
||||||
c->is_udp ? 'U' : 'u', c->is_connecting ? 'C' : 'c', n, len,
|
|
||||||
MG_SOCK_ERRNO, *fail));
|
|
||||||
if (n > 0 && c->is_hexdumping) {
|
|
||||||
char *s = mg_hexdump(buf, n);
|
|
||||||
LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "<-", n, s));
|
|
||||||
free(s);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ll_write(struct mg_connection *c, const void *buf, int len,
|
|
||||||
int *fail) {
|
|
||||||
int n = c->is_tls ? mg_tls_send(c, buf, len, fail)
|
|
||||||
: mg_sock_send(c, buf, len, fail);
|
|
||||||
LOG(*fail ? LL_ERROR : LL_VERBOSE_DEBUG,
|
|
||||||
("%lu %c%c%c %d/%d %d", c->id, c->is_tls ? 'T' : 't',
|
|
||||||
c->is_udp ? 'U' : 'u', c->is_connecting ? 'C' : 'c', n, len,
|
|
||||||
MG_SOCK_ERRNO));
|
|
||||||
if (n > 0 && c->is_hexdumping) {
|
|
||||||
char *s = mg_hexdump(buf, len);
|
|
||||||
LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "->", len, s));
|
|
||||||
free(s);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
|
||||||
int fail, n = c->is_udp
|
|
||||||
? ll_write(c, buf, (SOCKET) len, &fail)
|
|
||||||
: (int) mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
|
|
||||||
if (len > 0 && n == 0) fail = 1;
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_set_non_blocking_mode(SOCKET fd) {
|
static void mg_set_non_blocking_mode(SOCKET fd) {
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) && MG_ENABLE_WINSOCK
|
||||||
unsigned long on = 1;
|
unsigned long on = 1;
|
||||||
ioctlsocket(fd, FIONBIO, &on);
|
ioctlsocket(fd, FIONBIO, &on);
|
||||||
#elif MG_ARCH == MG_ARCH_FREERTOS
|
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
const BaseType_t off = 0;
|
const BaseType_t off = 0;
|
||||||
setsockopt(fd, 0, FREERTOS_SO_RCVTIMEO, &off, sizeof(off));
|
setsockopt(fd, 0, FREERTOS_SO_RCVTIMEO, &off, sizeof(off));
|
||||||
setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off));
|
setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off));
|
||||||
#else
|
#else
|
||||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
|
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK, FD_CLOEXEC);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET mg_open_listener(const char *url) {
|
SOCKET mg_open_listener(const char *url, struct mg_addr *addr) {
|
||||||
struct mg_addr addr;
|
|
||||||
SOCKET fd = INVALID_SOCKET;
|
SOCKET fd = INVALID_SOCKET;
|
||||||
|
memset(addr, 0, sizeof(*addr));
|
||||||
memset(&addr, 0, sizeof(addr));
|
addr->port = mg_htons(mg_url_port(url));
|
||||||
addr.port = mg_htons(mg_url_port(url));
|
if (!mg_aton(mg_url_host(url), addr)) {
|
||||||
if (!mg_aton(mg_url_host(url), &addr)) {
|
|
||||||
LOG(LL_ERROR, ("invalid listening URL: %s", url));
|
LOG(LL_ERROR, ("invalid listening URL: %s", url));
|
||||||
} else {
|
} else {
|
||||||
union usa usa = tousa(&addr);
|
union usa usa = tousa(addr);
|
||||||
int on = 1, af = AF_INET;
|
int on = 1, af = AF_INET;
|
||||||
int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
|
int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
|
||||||
int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
|
int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
|
||||||
socklen_t slen = sizeof(usa.sin);
|
socklen_t slen = sizeof(usa.sin);
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (addr.is_ip6) af = AF_INET6, slen = sizeof(usa.sin6);
|
if (addr->is_ip6) af = AF_INET6, slen = sizeof(usa.sin6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((fd = socket(af, type, proto)) != INVALID_SOCKET &&
|
if ((fd = socket(af, type, proto)) != INVALID_SOCKET &&
|
||||||
@@ -217,57 +167,121 @@ SOCKET mg_open_listener(const char *url) {
|
|||||||
bind(fd, &usa.sa, slen) == 0 &&
|
bind(fd, &usa.sa, slen) == 0 &&
|
||||||
// NOTE(lsm): FreeRTOS uses backlog value as a connection limit
|
// NOTE(lsm): FreeRTOS uses backlog value as a connection limit
|
||||||
(type == SOCK_DGRAM || listen(fd, 128) == 0)) {
|
(type == SOCK_DGRAM || listen(fd, 128) == 0)) {
|
||||||
|
// In case port was set to 0, get the real port number
|
||||||
|
if (getsockname(fd, &usa.sa, &slen) == 0) {
|
||||||
|
addr->port = usa.sin.sin_port;
|
||||||
|
#if MG_ENABLE_IPV6
|
||||||
|
if (addr->is_ip6) addr->port = usa.sin6.sin6_port;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
mg_set_non_blocking_mode(fd);
|
mg_set_non_blocking_mode(fd);
|
||||||
} else if (fd != INVALID_SOCKET) {
|
} else if (fd != INVALID_SOCKET) {
|
||||||
LOG(LL_ERROR, ("Failed to listen on %s, errno %d", url, MG_SOCK_ERRNO));
|
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
fd = INVALID_SOCKET;
|
fd = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fd == INVALID_SOCKET) {
|
||||||
|
LOG(LL_ERROR, ("Failed to listen on %s, errno %d", url, MG_SOCK_ERRNO));
|
||||||
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_conn(struct mg_connection *c,
|
static long mg_sock_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||||
int (*fn)(struct mg_connection *, void *, int, int *)) {
|
long n = 0;
|
||||||
unsigned char *buf;
|
if (c->is_udp) {
|
||||||
int rc, len, fail;
|
union usa usa;
|
||||||
|
socklen_t slen = sizeof(usa.sin);
|
||||||
// NOTE(lsm): do only one iteration of reads, cause some systems
|
#if MG_ENABLE_IPV6
|
||||||
// (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
|
if (c->peer.is_ip6) slen = sizeof(usa.sin6);
|
||||||
if (c->recv.size - c->recv.len < MG_IO_SIZE &&
|
#endif
|
||||||
c->recv.size < MG_MAX_RECV_BUF_SIZE &&
|
n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
|
||||||
!mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) {
|
if (n > 0) {
|
||||||
c->is_closing = 1;
|
if (c->peer.is_ip6) {
|
||||||
}
|
#if MG_ENABLE_IPV6
|
||||||
buf = c->recv.buf + c->recv.len;
|
memcpy(c->peer.ip6, &usa.sin6.sin6_addr, sizeof(c->peer.ip6));
|
||||||
len = (int) (c->recv.size - c->recv.len);
|
c->peer.port = usa.sin6.sin6_port;
|
||||||
rc = fn(c, buf, len, &fail);
|
#endif
|
||||||
if (rc > 0) {
|
} else {
|
||||||
struct mg_str evd = mg_str_n((char *) buf, rc);
|
c->peer.ip = *(uint32_t *) &usa.sin.sin_addr;
|
||||||
c->recv.len += rc;
|
c->peer.port = usa.sin.sin_port;
|
||||||
mg_call(c, MG_EV_READ, &evd);
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fail) c->is_closing = 1;
|
n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
|
||||||
|
}
|
||||||
|
return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(lsm): do only one iteration of reads, cause some systems
|
||||||
|
// (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
|
||||||
|
static void read_conn(struct mg_connection *c) {
|
||||||
|
if (c->recv.len >= MG_MAX_RECV_BUF_SIZE) {
|
||||||
|
mg_error(c, "max_recv_buf_size reached");
|
||||||
|
} else if (c->recv.size - c->recv.len < MG_IO_SIZE &&
|
||||||
|
!mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) {
|
||||||
|
mg_error(c, "oom");
|
||||||
|
} else {
|
||||||
|
char *buf = (char *) &c->recv.buf[c->recv.len];
|
||||||
|
size_t len = c->recv.size - c->recv.len;
|
||||||
|
long n = c->is_tls ? mg_tls_recv(c, buf, len) : mg_sock_recv(c, buf, len);
|
||||||
|
LOG(n > 0 ? LL_VERBOSE_DEBUG : LL_DEBUG,
|
||||||
|
("%-3lu %d%d%d%d%d%d%d%d%d%d%d%d%d%d %7ld %ld/%ld err %d", c->id,
|
||||||
|
c->is_listening, c->is_client, c->is_accepted, c->is_resolving,
|
||||||
|
c->is_connecting, c->is_tls, c->is_tls_hs, c->is_udp, c->is_websocket,
|
||||||
|
c->is_hexdumping, c->is_draining, c->is_closing, c->is_readable,
|
||||||
|
c->is_writable, (long) c->recv.len, n, (long) len, MG_SOCK_ERRNO));
|
||||||
|
if (n == 0) {
|
||||||
|
// Do nothing
|
||||||
|
} else if (n < 0) {
|
||||||
|
c->is_closing = 1; // Error, or normal termination
|
||||||
|
} else if (n > 0) {
|
||||||
|
struct mg_str evd = mg_str_n(buf, (size_t) n);
|
||||||
|
if (c->is_hexdumping) {
|
||||||
|
char *s = mg_hexdump(buf, (size_t) n);
|
||||||
|
LOG(LL_INFO, ("\n-- %lu %s %s %ld\n%s", c->id, c->label, "<-", n, s));
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
c->recv.len += (size_t) n;
|
||||||
|
mg_call(c, MG_EV_READ, &evd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_conn(struct mg_connection *c) {
|
static void write_conn(struct mg_connection *c) {
|
||||||
int fail, rc = ll_write(c, c->send.buf, (SOCKET) c->send.len, &fail);
|
char *buf = (char *) c->send.buf;
|
||||||
if (rc > 0) {
|
size_t len = c->send.len;
|
||||||
mg_iobuf_delete(&c->send, rc);
|
long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_sock_send(c, buf, len);
|
||||||
|
|
||||||
|
LOG(n > 0 ? LL_VERBOSE_DEBUG : LL_DEBUG,
|
||||||
|
("%-3lu %d%d%d%d%d%d%d%d%d%d%d%d%d%d %7ld %ld err %d", c->id,
|
||||||
|
c->is_listening, c->is_client, c->is_accepted, c->is_resolving,
|
||||||
|
c->is_connecting, c->is_tls, c->is_tls_hs, c->is_udp, c->is_websocket,
|
||||||
|
c->is_hexdumping, c->is_draining, c->is_closing, c->is_readable,
|
||||||
|
c->is_writable, (long) c->send.len, n, MG_SOCK_ERRNO));
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
// Do nothing
|
||||||
|
} else if (n < 0) {
|
||||||
|
c->is_closing = 1; // Error, or normal termination
|
||||||
|
} else if (n > 0) {
|
||||||
|
// Hexdump before deleting
|
||||||
|
if (c->is_hexdumping) {
|
||||||
|
char *s = mg_hexdump(buf, (size_t) n);
|
||||||
|
LOG(LL_INFO, ("\n-- %lu %s %s %ld\n%s", c->id, c->label, "<-", n, s));
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
mg_iobuf_delete(&c->send, (size_t) n);
|
||||||
if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
|
if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
|
||||||
mg_call(c, MG_EV_WRITE, &rc);
|
mg_call(c, MG_EV_WRITE, &n);
|
||||||
} else if (fail) {
|
// if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
|
||||||
c->is_closing = 1;
|
|
||||||
}
|
}
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_conn(struct mg_connection *c) {
|
static void close_conn(struct mg_connection *c) {
|
||||||
// Unlink this connection from the list
|
// Unlink this connection from the list
|
||||||
LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
|
|
||||||
mg_resolve_cancel(c);
|
mg_resolve_cancel(c);
|
||||||
|
LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
|
||||||
if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
|
if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
|
||||||
if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
|
if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
|
||||||
mg_call(c, MG_EV_CLOSE, NULL);
|
mg_call(c, MG_EV_CLOSE, NULL);
|
||||||
@@ -275,7 +289,7 @@ static void close_conn(struct mg_connection *c) {
|
|||||||
LOG(LL_DEBUG, ("%lu closed", c->id));
|
LOG(LL_DEBUG, ("%lu closed", c->id));
|
||||||
if (FD(c) != INVALID_SOCKET) {
|
if (FD(c) != INVALID_SOCKET) {
|
||||||
closesocket(FD(c));
|
closesocket(FD(c));
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL);
|
FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -287,8 +301,8 @@ static void close_conn(struct mg_connection *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void setsockopts(struct mg_connection *c) {
|
static void setsockopts(struct mg_connection *c) {
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
FreeRTOS_FD_SET(c->fd, c->mgr->ss, eSELECT_READ | eSELECT_EXCEPT);
|
(void) c;
|
||||||
#else
|
#else
|
||||||
int on = 1;
|
int on = 1;
|
||||||
#if !defined(SOL_TCP)
|
#if !defined(SOL_TCP)
|
||||||
@@ -316,12 +330,12 @@ static void setsockopts(struct mg_connection *c) {
|
|||||||
void mg_connect_resolved(struct mg_connection *c) {
|
void mg_connect_resolved(struct mg_connection *c) {
|
||||||
char buf[40];
|
char buf[40];
|
||||||
int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
|
int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
|
||||||
int af = AF_INET;
|
int rc, af = AF_INET;
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (c->peer.is_ip6) af = AF_INET6;
|
if (c->peer.is_ip6) af = AF_INET6;
|
||||||
#endif
|
#endif
|
||||||
mg_straddr(c, buf, sizeof(buf));
|
mg_straddr(c, buf, sizeof(buf));
|
||||||
c->fd = (void *) (long) socket(af, type, 0);
|
c->fd = sock2ptr(socket(af, type, 0));
|
||||||
if (FD(c) == INVALID_SOCKET) {
|
if (FD(c) == INVALID_SOCKET) {
|
||||||
mg_error(c, "socket(): %d", MG_SOCK_ERRNO);
|
mg_error(c, "socket(): %d", MG_SOCK_ERRNO);
|
||||||
return;
|
return;
|
||||||
@@ -331,19 +345,16 @@ void mg_connect_resolved(struct mg_connection *c) {
|
|||||||
mg_call(c, MG_EV_RESOLVE, NULL);
|
mg_call(c, MG_EV_RESOLVE, NULL);
|
||||||
if (type == SOCK_STREAM) {
|
if (type == SOCK_STREAM) {
|
||||||
union usa usa = tousa(&c->peer);
|
union usa usa = tousa(&c->peer);
|
||||||
socklen_t slen =
|
socklen_t slen = sizeof(usa.sin);
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
c->peer.is_ip6 ? sizeof(usa.sin6) :
|
if (c->peer.is_ip6) slen = sizeof(usa.sin6);
|
||||||
#endif
|
#endif
|
||||||
sizeof(usa.sin);
|
if ((rc = connect(FD(c), &usa.sa, slen)) == 0 || mg_sock_would_block()) {
|
||||||
int rc = connect(FD(c), &usa.sa, slen);
|
|
||||||
int fail = rc < 0 && mg_sock_failed() ? MG_SOCK_ERRNO : 0;
|
|
||||||
if (fail) {
|
|
||||||
mg_error(c, "connect: %d", MG_SOCK_ERRNO);
|
|
||||||
} else {
|
|
||||||
setsockopts(c);
|
setsockopts(c);
|
||||||
|
if (rc != 0) c->is_connecting = 1;
|
||||||
|
} else {
|
||||||
|
mg_error(c, "connect: %d", MG_SOCK_ERRNO);
|
||||||
}
|
}
|
||||||
if (rc < 0) c->is_connecting = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,8 +383,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
|
|||||||
SOCKET fd = accept(FD(lsn), &usa.sa, &sa_len);
|
SOCKET fd = accept(FD(lsn), &usa.sa, &sa_len);
|
||||||
if (fd == INVALID_SOCKET) {
|
if (fd == INVALID_SOCKET) {
|
||||||
LOG(LL_ERROR, ("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERRNO));
|
LOG(LL_ERROR, ("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERRNO));
|
||||||
#if !defined(_WIN32)
|
#if (!defined(_WIN32) && (MG_ARCH != MG_ARCH_FREERTOS_TCP))
|
||||||
} else if (fd >= FD_SETSIZE) {
|
} else if ((long) fd >= FD_SETSIZE) {
|
||||||
LOG(LL_ERROR, ("%ld > %ld", (long) fd, (long) FD_SETSIZE));
|
LOG(LL_ERROR, ("%ld > %ld", (long) fd, (long) FD_SETSIZE));
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
#endif
|
#endif
|
||||||
@@ -451,30 +462,33 @@ bool mg_socketpair(int *s1, int *s2) {
|
|||||||
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
||||||
mg_event_handler_t fn, void *fn_data) {
|
mg_event_handler_t fn, void *fn_data) {
|
||||||
struct mg_connection *c = NULL;
|
struct mg_connection *c = NULL;
|
||||||
int is_udp = strncmp(url, "udp:", 4) == 0;
|
bool is_udp = strncmp(url, "udp:", 4) == 0;
|
||||||
SOCKET fd = mg_open_listener(url);
|
struct mg_addr addr;
|
||||||
|
SOCKET fd = mg_open_listener(url, &addr);
|
||||||
if (fd == INVALID_SOCKET) {
|
if (fd == INVALID_SOCKET) {
|
||||||
} else if ((c = alloc_conn(mgr, 0, fd)) == NULL) {
|
} else if ((c = alloc_conn(mgr, 0, fd)) == NULL) {
|
||||||
LOG(LL_ERROR, ("OOM %s", url));
|
LOG(LL_ERROR, ("OOM %s", url));
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
} else {
|
} else {
|
||||||
c->fd = (void *) (long) fd;
|
memcpy(&c->peer, &addr, sizeof(struct mg_addr));
|
||||||
|
c->fd = sock2ptr(fd);
|
||||||
c->is_listening = 1;
|
c->is_listening = 1;
|
||||||
c->is_udp = is_udp;
|
c->is_udp = is_udp;
|
||||||
setsockopts(c);
|
|
||||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||||
c->fn = fn;
|
c->fn = fn;
|
||||||
c->fn_data = fn_data;
|
c->fn_data = fn_data;
|
||||||
LOG(LL_INFO, ("%lu accepting on %s", c->id, url));
|
LOG(LL_INFO,
|
||||||
|
("%lu accepting on %s (port %u)", c->id, url, mg_ntohs(c->peer.port)));
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
struct mg_connection *c;
|
struct mg_connection *c;
|
||||||
for (c = mgr->conns; c != NULL; c = c->next) {
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
FreeRTOS_FD_CLR(c->fd, mgr->ss, eSELECT_WRITE);
|
if (c->is_closing || c->is_resolving || FD(c) == INVALID_SOCKET) continue;
|
||||||
|
FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_READ | eSELECT_EXCEPT);
|
||||||
if (c->is_connecting || (c->send.len > 0 && c->is_tls_hs == 0))
|
if (c->is_connecting || (c->send.len > 0 && c->is_tls_hs == 0))
|
||||||
FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_WRITE);
|
FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_WRITE);
|
||||||
}
|
}
|
||||||
@@ -483,6 +497,8 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
|||||||
EventBits_t bits = FreeRTOS_FD_ISSET(c->fd, mgr->ss);
|
EventBits_t bits = FreeRTOS_FD_ISSET(c->fd, mgr->ss);
|
||||||
c->is_readable = bits & (eSELECT_READ | eSELECT_EXCEPT) ? 1 : 0;
|
c->is_readable = bits & (eSELECT_READ | eSELECT_EXCEPT) ? 1 : 0;
|
||||||
c->is_writable = bits & eSELECT_WRITE ? 1 : 0;
|
c->is_writable = bits & eSELECT_WRITE ? 1 : 0;
|
||||||
|
FreeRTOS_FD_CLR(c->fd, mgr->ss,
|
||||||
|
eSELECT_READ | eSELECT_EXCEPT | eSELECT_WRITE);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct timeval tv = {ms / 1000, (ms % 1000) * 1000};
|
struct timeval tv = {ms / 1000, (ms % 1000) * 1000};
|
||||||
@@ -523,8 +539,10 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
|||||||
|
|
||||||
static void connect_conn(struct mg_connection *c) {
|
static void connect_conn(struct mg_connection *c) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
#if MG_ARCH != MG_ARCH_FREERTOS_TCP
|
||||||
socklen_t len = sizeof(rc);
|
socklen_t len = sizeof(rc);
|
||||||
if (getsockopt(FD(c), SOL_SOCKET, SO_ERROR, (char *) &rc, &len)) rc = 1;
|
if (getsockopt(FD(c), SOL_SOCKET, SO_ERROR, (char *) &rc, &len)) rc = 1;
|
||||||
|
#endif
|
||||||
if (rc == EAGAIN || rc == EWOULDBLOCK) rc = 0;
|
if (rc == EAGAIN || rc == EWOULDBLOCK) rc = 0;
|
||||||
c->is_connecting = 0;
|
c->is_connecting = 0;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -561,7 +579,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
|||||||
} else if (c->is_tls_hs) {
|
} else if (c->is_tls_hs) {
|
||||||
if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
|
if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
|
||||||
} else {
|
} else {
|
||||||
if (c->is_readable) read_conn(c, ll_read);
|
if (c->is_readable) read_conn(c);
|
||||||
if (c->is_writable) write_conn(c);
|
if (c->is_writable) write_conn(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,16 +9,17 @@
|
|||||||
#if MG_ENABLE_SSI
|
#if MG_ENABLE_SSI
|
||||||
static char *mg_ssi(const char *path, const char *root, int depth) {
|
static char *mg_ssi(const char *path, const char *root, int depth) {
|
||||||
struct mg_iobuf b = {NULL, 0, 0};
|
struct mg_iobuf b = {NULL, 0, 0};
|
||||||
FILE *fp = mg_fopen(path, "rb");
|
FILE *fp = fopen(path, "rb");
|
||||||
if (fp != NULL) {
|
if (fp != NULL) {
|
||||||
char buf[BUFSIZ], arg[sizeof(buf)];
|
char buf[BUFSIZ], arg[sizeof(buf)];
|
||||||
int ch, intag = 0;
|
int ch, intag = 0;
|
||||||
size_t len = 0, align = MG_IO_SIZE;
|
size_t len = 0, align = MG_IO_SIZE;
|
||||||
while ((ch = fgetc(fp)) != EOF) {
|
while ((ch = fgetc(fp)) != EOF) {
|
||||||
if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
|
if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
|
||||||
buf[len++] = ch & 0xff;
|
buf[len++] = (char) (ch & 0xff);
|
||||||
if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) {
|
if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) {
|
||||||
char tmp[MG_PATH_MAX], *p = (char *) path + strlen(path), *data;
|
char tmp[MG_PATH_MAX + BUFSIZ + 10],
|
||||||
|
*p = (char *) path + strlen(path), *data;
|
||||||
while (p > path && p[-1] != MG_DIRSEP && p[-1] != '/') p--;
|
while (p > path && p[-1] != MG_DIRSEP && p[-1] != '/') p--;
|
||||||
snprintf(tmp, sizeof(tmp), "%.*s%s", (int) (p - path), path, arg);
|
snprintf(tmp, sizeof(tmp), "%.*s%s", (int) (p - path), path, arg);
|
||||||
if (depth < MG_MAX_SSI_DEPTH &&
|
if (depth < MG_MAX_SSI_DEPTH &&
|
||||||
@@ -29,7 +30,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
|
|||||||
LOG(LL_ERROR, ("%s: file=%s error or too deep", path, arg));
|
LOG(LL_ERROR, ("%s: file=%s error or too deep", path, arg));
|
||||||
}
|
}
|
||||||
} else if (sscanf(buf, "<!--#include virtual=\"%[^\"]", arg)) {
|
} else if (sscanf(buf, "<!--#include virtual=\"%[^\"]", arg)) {
|
||||||
char tmp[MG_PATH_MAX], *data;
|
char tmp[MG_PATH_MAX + BUFSIZ + 10], *data;
|
||||||
snprintf(tmp, sizeof(tmp), "%s%s", root, arg);
|
snprintf(tmp, sizeof(tmp), "%s%s", root, arg);
|
||||||
if (depth < MG_MAX_SSI_DEPTH &&
|
if (depth < MG_MAX_SSI_DEPTH &&
|
||||||
(data = mg_ssi(tmp, root, depth + 1)) != NULL) {
|
(data = mg_ssi(tmp, root, depth + 1)) != NULL) {
|
||||||
@@ -49,7 +50,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
|
|||||||
intag = 1;
|
intag = 1;
|
||||||
if (len > 0) mg_iobuf_append(&b, buf, len, align);
|
if (len > 0) mg_iobuf_append(&b, buf, len, align);
|
||||||
len = 0;
|
len = 0;
|
||||||
buf[len++] = ch & 0xff;
|
buf[len++] = (char) (ch & 0xff);
|
||||||
} else if (intag) {
|
} else if (intag) {
|
||||||
if (len == 5 && strncmp(buf, "<!--#", 5) != 0) {
|
if (len == 5 && strncmp(buf, "<!--#", 5) != 0) {
|
||||||
intag = 0;
|
intag = 0;
|
||||||
@@ -57,9 +58,9 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
|
|||||||
LOG(LL_ERROR, ("%s: SSI tag is too large", path));
|
LOG(LL_ERROR, ("%s: SSI tag is too large", path));
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
buf[len++] = ch & 0xff;
|
buf[len++] = (char) (ch & 0xff);
|
||||||
} else {
|
} else {
|
||||||
buf[len++] = ch & 0xff;
|
buf[len++] = (char) (ch & 0xff);
|
||||||
if (len >= sizeof(buf)) {
|
if (len >= sizeof(buf)) {
|
||||||
mg_iobuf_append(&b, buf, len, align);
|
mg_iobuf_append(&b, buf, len, align);
|
||||||
len = 0;
|
len = 0;
|
||||||
@@ -77,8 +78,9 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
|
|||||||
|
|
||||||
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
||||||
const char *fullpath) {
|
const char *fullpath) {
|
||||||
|
const char *headers = "Content-Type: text/html; charset=utf-8\r\n";
|
||||||
char *data = mg_ssi(fullpath, root, 0);
|
char *data = mg_ssi(fullpath, root, 0);
|
||||||
mg_http_reply(c, 200, "", "%s", data == NULL ? "" : data);
|
mg_http_reply(c, 200, headers, "%s", data == NULL ? "" : data);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
struct mg_str mg_str(const char *s) {
|
struct mg_str mg_str_s(const char *s) {
|
||||||
struct mg_str str = {s, s == NULL ? 0 : strlen(s)};
|
struct mg_str str = {s, s == NULL ? 0 : strlen(s)};
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ int mg_vcasecmp(const struct mg_str *str1, const char *str2) {
|
|||||||
struct mg_str mg_strdup(const struct mg_str s) {
|
struct mg_str mg_strdup(const struct mg_str s) {
|
||||||
struct mg_str r = {NULL, 0};
|
struct mg_str r = {NULL, 0};
|
||||||
if (s.len > 0 && s.ptr != NULL) {
|
if (s.len > 0 && s.ptr != NULL) {
|
||||||
char *sc = (char *) malloc(s.len + 1);
|
char *sc = (char *) calloc(1, s.len + 1);
|
||||||
if (sc != NULL) {
|
if (sc != NULL) {
|
||||||
memcpy(sc, s.ptr, s.len);
|
memcpy(sc, s.ptr, s.len);
|
||||||
sc[s.len] = '\0';
|
sc[s.len] = '\0';
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ struct mg_str {
|
|||||||
#define MG_NULL_STR \
|
#define MG_NULL_STR \
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
|
|
||||||
|
// Using macro to avoid shadowing C++ struct constructor, see #1298
|
||||||
|
#define mg_str(s) mg_str_s(s)
|
||||||
|
|
||||||
struct mg_str mg_str(const char *s);
|
struct mg_str mg_str(const char *s);
|
||||||
struct mg_str mg_str_n(const char *s, size_t n);
|
struct mg_str mg_str_n(const char *s, size_t n);
|
||||||
int mg_lower(const char *s);
|
int mg_lower(const char *s);
|
||||||
|
|||||||
+2
-2
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
struct mg_timer *g_timers;
|
struct mg_timer *g_timers;
|
||||||
|
|
||||||
void mg_timer_init(struct mg_timer *t, int ms, int flags, void (*fn)(void *),
|
void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
|
||||||
void *arg) {
|
void (*fn)(void *), void *arg) {
|
||||||
struct mg_timer tmp = {ms, flags, fn, arg, 0UL, g_timers};
|
struct mg_timer tmp = {ms, flags, fn, arg, 0UL, g_timers};
|
||||||
*t = tmp;
|
*t = tmp;
|
||||||
g_timers = t;
|
g_timers = t;
|
||||||
|
|||||||
+5
-4
@@ -1,18 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct mg_timer {
|
struct mg_timer {
|
||||||
int period_ms; // Timer period in milliseconds
|
unsigned long period_ms; // Timer period in milliseconds
|
||||||
int flags; // Possible flags values below
|
unsigned flags; // Possible flags values below
|
||||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||||
void (*fn)(void *); // Function to call
|
void (*fn)(void *); // Function to call
|
||||||
void *arg; // Function agrument
|
void *arg; // Function argument
|
||||||
unsigned long expire; // Expiration timestamp in milliseconds
|
unsigned long expire; // Expiration timestamp in milliseconds
|
||||||
struct mg_timer *next; // Linkage in g_timers list
|
struct mg_timer *next; // Linkage in g_timers list
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct mg_timer *g_timers; // Global list of timers
|
extern struct mg_timer *g_timers; // Global list of timers
|
||||||
|
|
||||||
void mg_timer_init(struct mg_timer *, int ms, int, void (*fn)(void *), void *);
|
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
||||||
|
void (*fn)(void *), void *);
|
||||||
void mg_timer_free(struct mg_timer *);
|
void mg_timer_free(struct mg_timer *);
|
||||||
void mg_timer_poll(unsigned long uptime_ms);
|
void mg_timer_poll(unsigned long uptime_ms);
|
||||||
@@ -16,6 +16,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||||
|
#define RNG , rng_get, NULL
|
||||||
|
#else
|
||||||
|
#define RNG
|
||||||
|
#endif
|
||||||
|
|
||||||
// Different versions have those in different files, so declare here
|
// Different versions have those in different files, so declare here
|
||||||
EXTERN_C int mbedtls_net_recv(void *, unsigned char *, size_t);
|
EXTERN_C int mbedtls_net_recv(void *, unsigned char *, size_t);
|
||||||
EXTERN_C int mbedtls_net_send(void *, const unsigned char *, size_t);
|
EXTERN_C int mbedtls_net_send(void *, const unsigned char *, size_t);
|
||||||
@@ -29,7 +35,7 @@ struct mg_tls {
|
|||||||
mbedtls_pk_context pk; // Private key context
|
mbedtls_pk_context pk; // Private key context
|
||||||
};
|
};
|
||||||
|
|
||||||
int mg_tls_handshake(struct mg_connection *c) {
|
void mg_tls_handshake(struct mg_connection *c) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
int rc;
|
int rc;
|
||||||
mbedtls_ssl_set_bio(&tls->ssl, &c->fd, mbedtls_net_send, mbedtls_net_recv, 0);
|
mbedtls_ssl_set_bio(&tls->ssl, &c->fd, mbedtls_net_send, mbedtls_net_recv, 0);
|
||||||
@@ -44,7 +50,6 @@ int mg_tls_handshake(struct mg_connection *c) {
|
|||||||
} else {
|
} else {
|
||||||
mg_error(c, "TLS handshake: -%#x", -rc); // Error
|
mg_error(c, "TLS handshake: -%#x", -rc); // Error
|
||||||
}
|
}
|
||||||
return rc == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
|
static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
|
||||||
@@ -54,32 +59,48 @@ static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
|
static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
|
||||||
n = strlen(s2) - 1;
|
n = (int) strlen(s2) - 1;
|
||||||
LOG(LL_VERBOSE_DEBUG, ("%p %.*s", ((struct mg_connection *) c)->fd, n, s2));
|
LOG(LL_VERBOSE_DEBUG, ("%p %.*s", ((struct mg_connection *) c)->fd, n, s2));
|
||||||
(void) s;
|
(void) s;
|
||||||
(void) c;
|
(void) c;
|
||||||
(void) lev;
|
(void) lev;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||||
|
static int rng_get(void *p_rng, unsigned char *buf, size_t len) {
|
||||||
|
(void) p_rng;
|
||||||
|
mg_random(buf, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
|
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
const char *ca = opts->ca == NULL ? "-"
|
const char *ca = opts->ca == NULL ? "-"
|
||||||
: opts->ca[0] == '-' ? "(emb)"
|
: opts->ca[0] == '-' ? "(emb)"
|
||||||
: opts->ca;
|
: opts->ca;
|
||||||
|
const char *cert = opts->cert == NULL ? "-"
|
||||||
|
: opts->cert[0] == '-' ? "(emb)"
|
||||||
|
: opts->cert;
|
||||||
|
const char *certkey = opts->certkey == NULL ? "-"
|
||||||
|
: opts->certkey[0] == '-' ? "(emb)"
|
||||||
|
: opts->certkey;
|
||||||
if (tls == NULL) {
|
if (tls == NULL) {
|
||||||
mg_error(c, "TLS OOM");
|
mg_error(c, "TLS OOM");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
LOG(LL_DEBUG, ("%lu Setting TLS, CA: %s, cert: %s, key: %s", c->id, ca,
|
LOG(LL_DEBUG, ("%lu Setting TLS, CA: %s, cert: %s, key: %s", c->id, ca,
|
||||||
opts->cert == NULL ? "null" : opts->cert,
|
cert, certkey));
|
||||||
opts->certkey == NULL ? "null" : opts->certkey));
|
|
||||||
mbedtls_ssl_init(&tls->ssl);
|
mbedtls_ssl_init(&tls->ssl);
|
||||||
mbedtls_ssl_config_init(&tls->conf);
|
mbedtls_ssl_config_init(&tls->conf);
|
||||||
|
mbedtls_x509_crt_init(&tls->ca);
|
||||||
|
mbedtls_x509_crt_init(&tls->cert);
|
||||||
|
mbedtls_pk_init(&tls->pk);
|
||||||
mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c);
|
mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c);
|
||||||
#if !defined(ESP_PLATFORM)
|
//#if !defined(ESP_PLATFORM)
|
||||||
mbedtls_debug_set_threshold(5);
|
// mbedtls_debug_set_threshold(5);
|
||||||
#endif
|
//#endif
|
||||||
if ((rc = mbedtls_ssl_config_defaults(
|
if ((rc = mbedtls_ssl_config_defaults(
|
||||||
&tls->conf,
|
&tls->conf,
|
||||||
c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||||
@@ -100,7 +121,6 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
mbedtls_x509_crt_init(&tls->ca);
|
|
||||||
rc = opts->ca[0] == '-'
|
rc = opts->ca[0] == '-'
|
||||||
? mbedtls_x509_crt_parse(&tls->ca, (uint8_t *) opts->ca,
|
? mbedtls_x509_crt_parse(&tls->ca, (uint8_t *) opts->ca,
|
||||||
strlen(opts->ca) + 1)
|
strlen(opts->ca) + 1)
|
||||||
@@ -112,23 +132,32 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, NULL);
|
mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (opts->srvname.len > 0) {
|
if (opts->srvname.len > 0) {
|
||||||
char buf[opts->srvname.len + 1];
|
char mem[128], *buf = mem;
|
||||||
sprintf(buf, "%.*s", (int) opts->srvname.len, opts->srvname.ptr);
|
mg_asprintf(&buf, sizeof(mem), "%.*s", (int) opts->srvname.len, opts->srvname.ptr);
|
||||||
mbedtls_ssl_set_hostname(&tls->ssl, buf);
|
mbedtls_ssl_set_hostname(&tls->ssl, buf);
|
||||||
|
if (buf != mem) free(buf);
|
||||||
}
|
}
|
||||||
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||||
}
|
}
|
||||||
if (opts->cert != NULL && opts->cert[0] != '\0') {
|
if (opts->cert != NULL && opts->cert[0] != '\0') {
|
||||||
const char *key = opts->certkey;
|
const char *key = opts->certkey;
|
||||||
if (key == NULL) key = opts->cert;
|
if (key == NULL) {
|
||||||
mbedtls_x509_crt_init(&tls->cert);
|
key = opts->cert;
|
||||||
mbedtls_pk_init(&tls->pk);
|
certkey = cert;
|
||||||
if ((rc = mbedtls_x509_crt_parse_file(&tls->cert, opts->cert)) != 0) {
|
}
|
||||||
mg_error(c, "parse(%s) err %#x", opts->cert, -rc);
|
rc = opts->cert[0] == '-'
|
||||||
|
? mbedtls_x509_crt_parse(&tls->cert, (uint8_t *) opts->cert,
|
||||||
|
strlen(opts->cert) + 1)
|
||||||
|
: mbedtls_x509_crt_parse_file(&tls->cert, opts->cert);
|
||||||
|
if (rc != 0) {
|
||||||
|
mg_error(c, "parse(%s) err %#x", cert, -rc);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((rc = mbedtls_pk_parse_keyfile(&tls->pk, key, NULL)) != 0) {
|
rc = key[0] == '-' ? mbedtls_pk_parse_key(&tls->pk, (uint8_t *) key,
|
||||||
mg_error(c, "tls key(%s) %#x", key, -rc);
|
strlen(key) + 1, NULL, 0 RNG)
|
||||||
|
: mbedtls_pk_parse_keyfile(&tls->pk, key, NULL RNG);
|
||||||
|
if (rc != 0) {
|
||||||
|
mg_error(c, "tls key(%s) %#x", certkey, -rc);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk);
|
rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk);
|
||||||
@@ -147,39 +176,35 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
|
if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
|
||||||
mg_tls_handshake(c);
|
mg_tls_handshake(c);
|
||||||
}
|
}
|
||||||
return 1;
|
return;
|
||||||
fail:
|
fail:
|
||||||
c->is_closing = 1;
|
c->is_closing = 1;
|
||||||
free(tls);
|
free(tls);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) {
|
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
int n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
|
long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
|
||||||
*fail = (n == 0) || (n < 0 && n != MBEDTLS_ERR_SSL_WANT_READ);
|
return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_READ ? 0 : n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len,
|
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
int *fail) {
|
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
int n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
|
long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
|
||||||
*fail = (n == 0) || (n < 0 && n != MBEDTLS_ERR_SSL_WANT_WRITE);
|
return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_WRITE ? 0 : n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_free(struct mg_connection *c) {
|
void mg_tls_free(struct mg_connection *c) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
if (tls == NULL) return 0;
|
if (tls == NULL) return;
|
||||||
free(tls->cafile);
|
free(tls->cafile);
|
||||||
mbedtls_x509_crt_free(&tls->ca);
|
|
||||||
mbedtls_x509_crt_free(&tls->cert);
|
|
||||||
mbedtls_ssl_free(&tls->ssl);
|
mbedtls_ssl_free(&tls->ssl);
|
||||||
mbedtls_pk_free(&tls->pk);
|
mbedtls_pk_free(&tls->pk);
|
||||||
|
mbedtls_x509_crt_free(&tls->ca);
|
||||||
|
mbedtls_x509_crt_free(&tls->cert);
|
||||||
mbedtls_ssl_config_free(&tls->conf);
|
mbedtls_ssl_config_free(&tls->conf);
|
||||||
free(tls);
|
free(tls);
|
||||||
return 1;
|
c->tls = NULL;
|
||||||
}
|
}
|
||||||
#elif MG_ENABLE_OPENSSL ///////////////////////////////////////// OPENSSL
|
#elif MG_ENABLE_OPENSSL ///////////////////////////////////////// OPENSSL
|
||||||
|
|
||||||
@@ -207,7 +232,7 @@ static int mg_tls_err(struct mg_tls *tls, int res) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
|
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
|
||||||
const char *id = "mongoose";
|
const char *id = "mongoose";
|
||||||
static unsigned char s_initialised = 0;
|
static unsigned char s_initialised = 0;
|
||||||
@@ -232,11 +257,13 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
mg_error(c, "SSL_new");
|
mg_error(c, "SSL_new");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
SSL_set_session_id_context(tls->ssl, (const uint8_t *) id, strlen(id));
|
SSL_set_session_id_context(tls->ssl, (const uint8_t *) id,
|
||||||
|
(unsigned) strlen(id));
|
||||||
// Disable deprecated protocols
|
// Disable deprecated protocols
|
||||||
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
|
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
|
||||||
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3);
|
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3);
|
||||||
SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1);
|
SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1);
|
||||||
|
SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1_1);
|
||||||
#ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION
|
#ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION
|
||||||
SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION);
|
SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION);
|
||||||
#endif
|
#endif
|
||||||
@@ -261,7 +288,7 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
} else if ((rc = SSL_use_PrivateKey_file(tls->ssl, key, 1)) != 1) {
|
} else if ((rc = SSL_use_PrivateKey_file(tls->ssl, key, 1)) != 1) {
|
||||||
mg_error(c, "Invalid SSL key, err %d", mg_tls_err(tls, rc));
|
mg_error(c, "Invalid SSL key, err %d", mg_tls_err(tls, rc));
|
||||||
goto fail;
|
goto fail;
|
||||||
#if OPENSSL_VERSION_NUMBER > 0x10002000L
|
#if OPENSSL_VERSION_NUMBER > 0x10100000L
|
||||||
} else if ((rc = SSL_use_certificate_chain_file(tls->ssl, opts->cert)) !=
|
} else if ((rc = SSL_use_certificate_chain_file(tls->ssl, opts->cert)) !=
|
||||||
1) {
|
1) {
|
||||||
mg_error(c, "Invalid CA, err %d", mg_tls_err(tls, rc));
|
mg_error(c, "Invalid CA, err %d", mg_tls_err(tls, rc));
|
||||||
@@ -276,9 +303,10 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
}
|
}
|
||||||
if (opts->ciphers != NULL) SSL_set_cipher_list(tls->ssl, opts->ciphers);
|
if (opts->ciphers != NULL) SSL_set_cipher_list(tls->ssl, opts->ciphers);
|
||||||
if (opts->srvname.len > 0) {
|
if (opts->srvname.len > 0) {
|
||||||
char buf[opts->srvname.len + 1];
|
char mem[128], *buf = mem;
|
||||||
sprintf(buf, "%.*s", (int) opts->srvname.len, opts->srvname.ptr);
|
mg_asprintf(&buf, sizeof(mem), "%.*s", (int) opts->srvname.len, opts->srvname.ptr);
|
||||||
SSL_set_tlsext_host_name(tls->ssl, buf);
|
SSL_set_tlsext_host_name(tls->ssl, buf);
|
||||||
|
if (buf != mem) free(buf);
|
||||||
}
|
}
|
||||||
c->tls = tls;
|
c->tls = tls;
|
||||||
c->is_tls = 1;
|
c->is_tls = 1;
|
||||||
@@ -288,75 +316,65 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
|||||||
}
|
}
|
||||||
c->is_hexdumping = 1;
|
c->is_hexdumping = 1;
|
||||||
LOG(LL_DEBUG, ("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
|
LOG(LL_DEBUG, ("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
|
||||||
return 1;
|
return;
|
||||||
fail:
|
fail:
|
||||||
c->is_closing = 1;
|
c->is_closing = 1;
|
||||||
free(tls);
|
free(tls);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_handshake(struct mg_connection *c) {
|
void mg_tls_handshake(struct mg_connection *c) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
int rc;
|
int rc;
|
||||||
SSL_set_fd(tls->ssl, (long) c->fd);
|
SSL_set_fd(tls->ssl, (int) (long) c->fd);
|
||||||
rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl);
|
rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl);
|
||||||
if (rc == 1) {
|
if (rc == 1) {
|
||||||
LOG(LL_DEBUG, ("%lu success", c->id));
|
LOG(LL_DEBUG, ("%lu success", c->id));
|
||||||
c->is_tls_hs = 0;
|
c->is_tls_hs = 0;
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
int code;
|
int code;
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
code = mg_tls_err(tls, rc);
|
code = mg_tls_err(tls, rc);
|
||||||
if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
|
if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_free(struct mg_connection *c) {
|
void mg_tls_free(struct mg_connection *c) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
if (tls == NULL) return 0;
|
if (tls == NULL) return;
|
||||||
SSL_free(tls->ssl);
|
SSL_free(tls->ssl);
|
||||||
SSL_CTX_free(tls->ctx);
|
SSL_CTX_free(tls->ctx);
|
||||||
free(tls);
|
free(tls);
|
||||||
return 1;
|
c->tls = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) {
|
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
int n = SSL_read(tls->ssl, buf, len);
|
int n = SSL_read(tls->ssl, buf, (int) len);
|
||||||
*fail = (n == 0) || (n < 0 && mg_tls_err(tls, n) != 0);
|
return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len,
|
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
int *fail) {
|
|
||||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||||
int n = SSL_write(tls->ssl, buf, len);
|
int n = SSL_write(tls->ssl, buf, (int) len);
|
||||||
*fail = (n == 0) || (n < 0 && mg_tls_err(tls, n) != 0);
|
return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else ////////////////////////////////////////// NO TLS
|
#else ////////////////////////////////////////// NO TLS
|
||||||
|
|
||||||
int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
|
||||||
(void) opts;
|
(void) opts;
|
||||||
mg_error(c, "TLS is not enabled");
|
mg_error(c, "TLS is not enabled");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
int mg_tls_handshake(struct mg_connection *c) {
|
void mg_tls_handshake(struct mg_connection *c) {
|
||||||
return c != NULL;
|
(void) c;
|
||||||
}
|
}
|
||||||
int mg_tls_free(struct mg_connection *c) {
|
void mg_tls_free(struct mg_connection *c) {
|
||||||
return c != NULL;
|
(void) c;
|
||||||
}
|
}
|
||||||
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) {
|
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||||
*fail = 1;
|
|
||||||
return c == NULL || buf == NULL || len == 0 ? 0 : -1;
|
return c == NULL || buf == NULL || len == 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len,
|
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
int *fail) {
|
|
||||||
*fail = 1;
|
|
||||||
return c == NULL || buf == NULL || len == 0 ? 0 : -1;
|
return c == NULL || buf == NULL || len == 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ struct mg_tls_opts {
|
|||||||
struct mg_str srvname; // If not empty, enables server name verification
|
struct mg_str srvname; // If not empty, enables server name verification
|
||||||
};
|
};
|
||||||
|
|
||||||
int mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
|
void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
|
||||||
int mg_tls_free(struct mg_connection *);
|
void mg_tls_free(struct mg_connection *);
|
||||||
int mg_tls_send(struct mg_connection *, const void *buf, size_t len, int *fail);
|
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
|
||||||
int mg_tls_recv(struct mg_connection *, void *buf, size_t len, int *fail);
|
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
|
||||||
int mg_tls_handshake(struct mg_connection *);
|
void mg_tls_handshake(struct mg_connection *);
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "url.h"
|
#include "url.h"
|
||||||
|
|
||||||
struct url {
|
struct url {
|
||||||
int key, user, pass, host, port, uri, end;
|
size_t key, user, pass, host, port, uri, end;
|
||||||
};
|
};
|
||||||
|
|
||||||
int mg_url_is_ssl(const char *url) {
|
int mg_url_is_ssl(const char *url) {
|
||||||
@@ -12,23 +12,23 @@ int mg_url_is_ssl(const char *url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct url urlparse(const char *url) {
|
static struct url urlparse(const char *url) {
|
||||||
int i;
|
size_t i;
|
||||||
struct url u;
|
struct url u;
|
||||||
memset(&u, 0, sizeof(u));
|
memset(&u, 0, sizeof(u));
|
||||||
for (i = 0; url[i] != '\0'; i++) {
|
for (i = 0; url[i] != '\0'; i++) {
|
||||||
if (i > 0 && url[i - 1] == '/' && url[i] == '/') {
|
if (i > 0 && u.host == 0 && url[i - 1] == '/' && url[i] == '/') {
|
||||||
u.host = i + 1;
|
u.host = i + 1;
|
||||||
u.port = 0;
|
u.port = 0;
|
||||||
} else if (url[i] == ']') {
|
} else if (url[i] == ']') {
|
||||||
u.port = 0; // IPv6 URLs, like http://[::1]/bar
|
u.port = 0; // IPv6 URLs, like http://[::1]/bar
|
||||||
} else if (url[i] == ':') {
|
} else if (url[i] == ':' && u.port == 0) {
|
||||||
u.port = i + 1;
|
u.port = i + 1;
|
||||||
} else if (url[i] == '@') {
|
} else if (url[i] == '@' && u.user == 0 && u.pass == 0) {
|
||||||
u.user = u.host;
|
u.user = u.host;
|
||||||
u.pass = u.port;
|
u.pass = u.port;
|
||||||
u.host = i + 1;
|
u.host = i + 1;
|
||||||
u.port = 0;
|
u.port = 0;
|
||||||
} else if (u.host && !u.uri && url[i] == '/') {
|
} else if (u.host && u.uri == 0 && url[i] == '/') {
|
||||||
u.uri = i;
|
u.uri = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,8 +41,9 @@ static struct url urlparse(const char *url) {
|
|||||||
|
|
||||||
struct mg_str mg_url_host(const char *url) {
|
struct mg_str mg_url_host(const char *url) {
|
||||||
struct url u = urlparse(url);
|
struct url u = urlparse(url);
|
||||||
int n =
|
size_t n = u.port ? u.port - u.host - 1
|
||||||
u.port ? u.port - u.host - 1 : u.uri ? u.uri - u.host : u.end - u.host;
|
: u.uri ? u.uri - u.host
|
||||||
|
: u.end - u.host;
|
||||||
struct mg_str s = mg_str_n(url + u.host, n);
|
struct mg_str s = mg_str_n(url + u.host, n);
|
||||||
if (s.len > 2 && s.ptr[0] == '[' && s.ptr[s.len - 1] == ']') {
|
if (s.len > 2 && s.ptr[0] == '[' && s.ptr[s.len - 1] == ']') {
|
||||||
s.len -= 2;
|
s.len -= 2;
|
||||||
@@ -63,7 +64,7 @@ unsigned short mg_url_port(const char *url) {
|
|||||||
if (memcmp(url, "wss:", 4) == 0 || memcmp(url, "https:", 6) == 0) port = 443;
|
if (memcmp(url, "wss:", 4) == 0 || memcmp(url, "https:", 6) == 0) port = 443;
|
||||||
if (memcmp(url, "mqtt:", 5) == 0) port = 1883;
|
if (memcmp(url, "mqtt:", 5) == 0) port = 1883;
|
||||||
if (memcmp(url, "mqtts:", 6) == 0) port = 8883;
|
if (memcmp(url, "mqtts:", 6) == 0) port = 8883;
|
||||||
if (u.port) port = atoi(url + u.port);
|
if (u.port) port = (unsigned short) atoi(url + u.port);
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ struct mg_str mg_url_user(const char *url) {
|
|||||||
struct url u = urlparse(url);
|
struct url u = urlparse(url);
|
||||||
struct mg_str s = mg_str("");
|
struct mg_str s = mg_str("");
|
||||||
if (u.user && (u.pass || u.host)) {
|
if (u.user && (u.pass || u.host)) {
|
||||||
int n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1;
|
size_t n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1;
|
||||||
s = mg_str_n(url + u.user, n);
|
s = mg_str_n(url + u.user, n);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@@ -79,9 +80,9 @@ struct mg_str mg_url_user(const char *url) {
|
|||||||
|
|
||||||
struct mg_str mg_url_pass(const char *url) {
|
struct mg_str mg_url_pass(const char *url) {
|
||||||
struct url u = urlparse(url);
|
struct url u = urlparse(url);
|
||||||
struct mg_str s = mg_str("");
|
struct mg_str s = mg_str_n("", 0UL);
|
||||||
if (u.pass && u.host) {
|
if (u.pass && u.host) {
|
||||||
int n = u.host - u.pass - 1;
|
size_t n = u.host - u.pass - 1;
|
||||||
s = mg_str_n(url + u.pass, n);
|
s = mg_str_n(url + u.pass, n);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
+67
-65
@@ -1,4 +1,5 @@
|
|||||||
#include "config.h"
|
#include "config.h" // Must go first - important for test++
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#if MG_ENABLE_FS
|
#if MG_ENABLE_FS
|
||||||
@@ -12,19 +13,8 @@ int mg_stat(const char *path, mg_stat_t *st) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *mg_fopen(const char *path, const char *mode) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
wchar_t b1[MG_PATH_MAX], b2[10];
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
|
|
||||||
return _wfopen(b1, b2);
|
|
||||||
#else
|
|
||||||
return fopen(path, mode);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t mg_file_size(const char *path) {
|
int64_t mg_file_size(const char *path) {
|
||||||
#if MG_ARCH == MG_ARCH_FREERTOS
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP && defined(MG_ENABLE_FF)
|
||||||
struct FF_STAT st;
|
struct FF_STAT st;
|
||||||
return ff_stat(path, &st) == 0 ? st.st_size : 0;
|
return ff_stat(path, &st) == 0 ? st.st_size : 0;
|
||||||
#else
|
#else
|
||||||
@@ -33,18 +23,19 @@ int64_t mg_file_size(const char *path) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mg_file_read(const char *path) {
|
char *mg_file_read(const char *path, size_t *sizep) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
size_t size = (size_t) mg_file_size(path);
|
size_t size = (size_t) mg_file_size(path);
|
||||||
if ((fp = mg_fopen(path, "rb")) != NULL) {
|
if ((fp = fopen(path, "rb")) != NULL) {
|
||||||
data = (char *) malloc(size + 1);
|
data = (char *) calloc(1, size + 1);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
if (fread(data, 1, size, fp) != size) {
|
if (fread(data, 1, size, fp) != size) {
|
||||||
free(data);
|
free(data);
|
||||||
data = NULL;
|
data = NULL;
|
||||||
} else {
|
} else {
|
||||||
data[size] = '\0';
|
data[size] = '\0';
|
||||||
|
if (sizep != NULL) *sizep = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -57,7 +48,7 @@ bool mg_file_write(const char *path, const void *buf, size_t len) {
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
char tmp[MG_PATH_MAX];
|
char tmp[MG_PATH_MAX];
|
||||||
snprintf(tmp, sizeof(tmp), "%s.%d", path, rand());
|
snprintf(tmp, sizeof(tmp), "%s.%d", path, rand());
|
||||||
fp = mg_fopen(tmp, "wb");
|
fp = fopen(tmp, "wb");
|
||||||
if (fp != NULL) {
|
if (fp != NULL) {
|
||||||
result = fwrite(buf, 1, len, fp) == len;
|
result = fwrite(buf, 1, len, fp) == len;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -74,36 +65,38 @@ bool mg_file_write(const char *path, const void *buf, size_t len) {
|
|||||||
bool mg_file_printf(const char *path, const char *fmt, ...) {
|
bool mg_file_printf(const char *path, const char *fmt, ...) {
|
||||||
char tmp[256], *buf = tmp;
|
char tmp[256], *buf = tmp;
|
||||||
bool result;
|
bool result;
|
||||||
size_t len;
|
int len;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap);
|
len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
result = mg_file_write(path, buf, len);
|
result = mg_file_write(path, buf, len > 0 ? (size_t) len : 0);
|
||||||
if (buf != tmp) free(buf);
|
if (buf != tmp) free(buf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // MG_ENABLE_FS
|
||||||
|
|
||||||
void mg_random(void *buf, size_t len) {
|
void mg_random(void *buf, size_t len) {
|
||||||
bool done = false;
|
bool done = false;
|
||||||
#if MG_ENABLE_FS
|
unsigned char *p = (unsigned char *) buf;
|
||||||
FILE *fp = mg_fopen("/dev/urandom", "rb");
|
#if MG_ARCH == MG_ARCH_ESP32
|
||||||
|
while (len--) *p++ = (unsigned char) (esp_random() & 255);
|
||||||
|
#elif MG_ARCH == MG_ARCH_WIN32
|
||||||
|
#elif MG_ARCH_UNIX && MG_ENABLE_FS
|
||||||
|
FILE *fp = fopen("/dev/urandom", "rb");
|
||||||
if (fp != NULL) {
|
if (fp != NULL) {
|
||||||
fread(buf, 1, len, fp);
|
if (fread(buf, 1, len, fp) == len) done = true;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
done = true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!done) {
|
|
||||||
// Fallback to a pseudo random gen
|
// Fallback to a pseudo random gen
|
||||||
size_t i;
|
if (!done) {
|
||||||
for (i = 0; i < len; i++) ((unsigned char *) buf)[i] = rand() % 0xff;
|
while (len--) *p++ = (unsigned char) (rand() & 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mg_globmatch(const char *s1, int n1, const char *s2, int n2) {
|
bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) {
|
||||||
int i = 0, j = 0, ni = 0, nj = 0;
|
size_t i = 0, j = 0, ni = 0, nj = 0;
|
||||||
while (i < n1 || j < n2) {
|
while (i < n1 || j < n2) {
|
||||||
if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
|
if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
|
||||||
i++, j++;
|
i++, j++;
|
||||||
@@ -118,21 +111,22 @@ bool mg_globmatch(const char *s1, int n1, const char *s2, int n2) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_nextcommaentry(const char *s, int slen, int ofs, int *koff,
|
static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff,
|
||||||
int *klen, int *voff, int *vlen) {
|
size_t *klen, size_t *voff, size_t *vlen) {
|
||||||
int kvlen, kl;
|
size_t kvlen, kl;
|
||||||
for (kvlen = 0; ofs + kvlen < slen && s[ofs + kvlen] != ',';) kvlen++;
|
for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != ',';) kvlen++;
|
||||||
for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++;
|
for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++;
|
||||||
if (koff != NULL) *koff = ofs;
|
if (koff != NULL) *koff = ofs;
|
||||||
if (klen != NULL) *klen = kl;
|
if (klen != NULL) *klen = kl;
|
||||||
if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0;
|
if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0;
|
||||||
if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0;
|
if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0;
|
||||||
return ofs >= slen ? slen : ofs + kvlen + 1;
|
ofs += kvlen + 1;
|
||||||
|
return ofs > n ? n : ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
|
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
|
||||||
int koff, klen, voff, vlen;
|
size_t koff = 0, klen = 0, voff = 0, vlen = 0;
|
||||||
int off = mg_nextcommaentry(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen);
|
size_t off = mg_nce(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen);
|
||||||
if (k != NULL) *k = mg_str_n(s->ptr + koff, klen);
|
if (k != NULL) *k = mg_str_n(s->ptr + koff, klen);
|
||||||
if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen);
|
if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen);
|
||||||
*s = mg_str_n(s->ptr + off, s->len - off);
|
*s = mg_str_n(s->ptr + off, s->len - off);
|
||||||
@@ -142,45 +136,47 @@ bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
|
|||||||
uint32_t mg_ntohl(uint32_t net) {
|
uint32_t mg_ntohl(uint32_t net) {
|
||||||
uint8_t data[4] = {0, 0, 0, 0};
|
uint8_t data[4] = {0, 0, 0, 0};
|
||||||
memcpy(&data, &net, sizeof(data));
|
memcpy(&data, &net, sizeof(data));
|
||||||
return ((uint32_t) data[3] << 0) | ((uint32_t) data[2] << 8) |
|
return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
|
||||||
((uint32_t) data[1] << 16) | ((uint32_t) data[0] << 24);
|
(((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t mg_ntohs(uint16_t net) {
|
uint16_t mg_ntohs(uint16_t net) {
|
||||||
uint8_t data[2] = {0, 0};
|
uint8_t data[2] = {0, 0};
|
||||||
memcpy(&data, &net, sizeof(data));
|
memcpy(&data, &net, sizeof(data));
|
||||||
return ((uint16_t) data[1] << 0) | ((uint32_t) data[0] << 8);
|
return (uint16_t)((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mg_hexdump(const void *buf, size_t len) {
|
char *mg_hexdump(const void *buf, size_t len) {
|
||||||
const unsigned char *p = (const unsigned char *) buf;
|
const unsigned char *p = (const unsigned char *) buf;
|
||||||
size_t i, idx, n = 0, ofs = 0, dlen = len * 5 + 100;
|
size_t i, idx, n = 0, ofs = 0, dlen = len * 5 + 100;
|
||||||
char ascii[17] = "", *dst = (char *) malloc(dlen);
|
char ascii[17] = "", *dst = (char *) calloc(1, dlen);
|
||||||
if (dst == NULL) return dst;
|
if (dst == NULL) return dst;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
idx = i % 16;
|
idx = i % 16;
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
if (i > 0 && dlen > n) n += snprintf(dst + n, dlen - n, " %s\n", ascii);
|
if (i > 0 && dlen > n)
|
||||||
if (dlen > n) n += snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs));
|
n += (size_t) snprintf(dst + n, dlen - n, " %s\n", ascii);
|
||||||
|
if (dlen > n)
|
||||||
|
n += (size_t) snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs));
|
||||||
}
|
}
|
||||||
if (dlen < n) break;
|
if (dlen < n) break;
|
||||||
n += snprintf(dst + n, dlen - n, " %02x", p[i]);
|
n += (size_t) snprintf(dst + n, dlen - n, " %02x", p[i]);
|
||||||
ascii[idx] = p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i];
|
ascii[idx] = (char) (p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]);
|
||||||
ascii[idx + 1] = '\0';
|
ascii[idx + 1] = '\0';
|
||||||
}
|
}
|
||||||
while (i++ % 16) {
|
while (i++ % 16) {
|
||||||
if (n < dlen) n += snprintf(dst + n, dlen - n, "%s", " ");
|
if (n < dlen) n += (size_t) snprintf(dst + n, dlen - n, "%s", " ");
|
||||||
}
|
}
|
||||||
if (n < dlen) n += snprintf(dst + n, dlen - n, " %s\n", ascii);
|
if (n < dlen) n += (size_t) snprintf(dst + n, dlen - n, " %s\n", ascii);
|
||||||
if (n > dlen - 1) n = dlen - 1;
|
if (n > dlen - 1) n = dlen - 1;
|
||||||
dst[n] = '\0';
|
dst[n] = '\0';
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mg_hex(const void *buf, int len, char *to) {
|
char *mg_hex(const void *buf, size_t len, char *to) {
|
||||||
const unsigned char *p = (const unsigned char *) buf;
|
const unsigned char *p = (const unsigned char *) buf;
|
||||||
static const char *hex = "0123456789abcdef";
|
static const char *hex = "0123456789abcdef";
|
||||||
int i = 0;
|
size_t i = 0;
|
||||||
for (; len--; p++) {
|
for (; len--; p++) {
|
||||||
to[i++] = hex[p[0] >> 4];
|
to[i++] = hex[p[0] >> 4];
|
||||||
to[i++] = hex[p[0] & 0x0f];
|
to[i++] = hex[p[0] & 0x0f];
|
||||||
@@ -189,19 +185,20 @@ char *mg_hex(const void *buf, int len, char *to) {
|
|||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long mg_unhexn(const char *s, int len) {
|
static unsigned char mg_unhex_nimble(unsigned char c) {
|
||||||
|
return (c >= '0' && c <= '9') ? (unsigned char) (c - '0')
|
||||||
|
: (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
|
||||||
|
: (unsigned char) (c - 'W');
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long mg_unhexn(const char *s, size_t len) {
|
||||||
unsigned long i = 0, v = 0;
|
unsigned long i = 0, v = 0;
|
||||||
for (i = 0; i < (unsigned long) len; i++) {
|
for (i = 0; i < len; i++) v <<= 4, v |= mg_unhex_nimble(((uint8_t *) s)[i]);
|
||||||
int c = s[i];
|
|
||||||
if (i > 0) v <<= 4;
|
|
||||||
v |= (c >= '0' && c <= '9') ? c - '0'
|
|
||||||
: (c >= 'A' && c <= 'F') ? c - '7' : c - 'W';
|
|
||||||
}
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_unhex(const char *buf, int len, unsigned char *to) {
|
void mg_unhex(const char *buf, size_t len, unsigned char *to) {
|
||||||
int i;
|
size_t i;
|
||||||
for (i = 0; i < len; i += 2) {
|
for (i = 0; i < len; i += 2) {
|
||||||
to[i >> 1] = (unsigned char) mg_unhexn(&buf[i], 2);
|
to[i >> 1] = (unsigned char) mg_unhexn(&buf[i], 2);
|
||||||
}
|
}
|
||||||
@@ -225,7 +222,7 @@ int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
|||||||
free(*buf);
|
free(*buf);
|
||||||
if (size == 0) size = 5;
|
if (size == 0) size = 5;
|
||||||
size *= 2;
|
size *= 2;
|
||||||
if ((*buf = (char *) malloc(size)) == NULL) {
|
if ((*buf = (char *) calloc(1, size)) == NULL) {
|
||||||
len = -1;
|
len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -239,11 +236,11 @@ int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
|||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
} else if (len >= (int) size) {
|
} else if (len >= (int) size) {
|
||||||
/// Standard-compliant code path. Allocate a buffer that is large enough
|
/// Standard-compliant code path. Allocate a buffer that is large enough
|
||||||
if ((*buf = (char *) malloc(len + 1)) == NULL) {
|
if ((*buf = (char *) calloc(1, (size_t) len + 1)) == NULL) {
|
||||||
len = -1; // LCOV_EXCL_LINE
|
len = -1; // LCOV_EXCL_LINE
|
||||||
} else { // LCOV_EXCL_LINE
|
} else { // LCOV_EXCL_LINE
|
||||||
va_copy(ap_copy, ap);
|
va_copy(ap_copy, ap);
|
||||||
len = vsnprintf(*buf, len + 1, fmt, ap_copy);
|
len = vsnprintf(*buf, (size_t) len + 1, fmt, ap_copy);
|
||||||
va_end(ap_copy);
|
va_end(ap_copy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,11 +258,12 @@ int mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t mg_to64(struct mg_str str) {
|
int64_t mg_to64(struct mg_str str) {
|
||||||
int64_t result = 0, neg = 1;
|
int64_t result = 0, neg = 1, max = 922337203685477570 /* INT64_MAX/10-10 */;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < str.len && (str.ptr[i] == ' ' || str.ptr[i] == '\t')) i++;
|
while (i < str.len && (str.ptr[i] == ' ' || str.ptr[i] == '\t')) i++;
|
||||||
if (i < str.len && str.ptr[i] == '-') neg = -1, i++;
|
if (i < str.len && str.ptr[i] == '-') neg = -1, i++;
|
||||||
while (i < str.len && str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
while (i < str.len && str.ptr[i] >= '0' && str.ptr[i] <= '9') {
|
||||||
|
if (result > max) return 0;
|
||||||
result *= 10;
|
result *= 10;
|
||||||
result += (str.ptr[i] - '0');
|
result += (str.ptr[i] - '0');
|
||||||
i++;
|
i++;
|
||||||
@@ -301,6 +299,8 @@ double mg_time(void) {
|
|||||||
((int64_t) ftime.dwHighDateTime << 32)) /
|
((int64_t) ftime.dwHighDateTime << 32)) /
|
||||||
10000000.0) -
|
10000000.0) -
|
||||||
11644473600;
|
11644473600;
|
||||||
|
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||||||
|
return mg_millis() / 1000.0;
|
||||||
#else
|
#else
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
if (gettimeofday(&tv, NULL /* tz */) != 0) return 0;
|
if (gettimeofday(&tv, NULL /* tz */) != 0) return 0;
|
||||||
@@ -313,8 +313,10 @@ void mg_usleep(unsigned long usecs) {
|
|||||||
Sleep(usecs / 1000);
|
Sleep(usecs / 1000);
|
||||||
#elif MG_ARCH == MG_ARCH_ESP8266
|
#elif MG_ARCH == MG_ARCH_ESP8266
|
||||||
ets_delay_us(usecs);
|
ets_delay_us(usecs);
|
||||||
|
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(usecs / 1000));
|
||||||
#else
|
#else
|
||||||
usleep(usecs);
|
usleep((useconds_t) usecs);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,13 +326,13 @@ unsigned long mg_millis(void) {
|
|||||||
#elif MG_ARCH == MG_ARCH_ESP32
|
#elif MG_ARCH == MG_ARCH_ESP32
|
||||||
return esp_timer_get_time() / 1000;
|
return esp_timer_get_time() / 1000;
|
||||||
#elif MG_ARCH == MG_ARCH_ESP8266
|
#elif MG_ARCH == MG_ARCH_ESP8266
|
||||||
// return system_get_time() / 1000;
|
|
||||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||||
#elif MG_ARCH == MG_ARCH_FREERTOS
|
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||||
#else
|
#else
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
return (unsigned long) ((uint64_t) ts.tv_sec * 1000 +
|
||||||
|
(uint64_t) ts.tv_nsec / 1000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
+24
-26
@@ -3,20 +3,33 @@
|
|||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
|
|
||||||
char *mg_file_read(const char *path);
|
// WEAK symbol makes it possible to define a "default" function implementation,
|
||||||
|
// which could be overridden by the user who can define a function with the
|
||||||
|
// same name without linking conflict
|
||||||
|
#if !defined(WEAK)
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__) || \
|
||||||
|
defined(__TI_COMPILER_VERSION__)) && \
|
||||||
|
!defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
#define WEAK __attribute__((weak))
|
||||||
|
#else
|
||||||
|
#define WEAK
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *mg_file_read(const char *path, size_t *size);
|
||||||
int64_t mg_file_size(const char *path);
|
int64_t mg_file_size(const char *path);
|
||||||
bool mg_file_write(const char *path, const void *buf, size_t len);
|
bool mg_file_write(const char *path, const void *buf, size_t len);
|
||||||
bool mg_file_printf(const char *path, const char *fmt, ...);
|
bool mg_file_printf(const char *path, const char *fmt, ...);
|
||||||
void mg_random(void *buf, size_t len);
|
void mg_random(void *buf, size_t len) WEAK;
|
||||||
bool mg_globmatch(const char *pattern, int plen, const char *s, int n);
|
bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
|
||||||
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||||||
uint16_t mg_ntohs(uint16_t net);
|
uint16_t mg_ntohs(uint16_t net);
|
||||||
uint32_t mg_ntohl(uint32_t net);
|
uint32_t mg_ntohl(uint32_t net);
|
||||||
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
||||||
char *mg_hexdump(const void *buf, size_t len);
|
char *mg_hexdump(const void *buf, size_t len);
|
||||||
char *mg_hex(const void *buf, int len, char *dst);
|
char *mg_hex(const void *buf, size_t len, char *dst);
|
||||||
void mg_unhex(const char *buf, int len, unsigned char *to);
|
void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||||||
unsigned long mg_unhexn(const char *s, int len);
|
unsigned long mg_unhexn(const char *s, size_t len);
|
||||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||||
int64_t mg_to64(struct mg_str str);
|
int64_t mg_to64(struct mg_str str);
|
||||||
@@ -31,26 +44,11 @@ typedef struct _stati64 mg_stat_t;
|
|||||||
typedef struct stat mg_stat_t;
|
typedef struct stat mg_stat_t;
|
||||||
#endif
|
#endif
|
||||||
int mg_stat(const char *path, mg_stat_t *);
|
int mg_stat(const char *path, mg_stat_t *);
|
||||||
FILE *mg_fopen(const char *fp, const char *mode);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define mg_htons(x) mg_ntohs(x)
|
#define mg_htons(x) mg_ntohs(x)
|
||||||
#define mg_htonl(x) mg_ntohl(x)
|
#define mg_htonl(x) mg_ntohl(x)
|
||||||
|
|
||||||
#define MG_SWAP16(x) ((((x) >> 8) & 255) | ((x & 255) << 8))
|
|
||||||
#define MG_SWAP32(x) \
|
|
||||||
(((x) >> 24) | (((x) &0xff0000) >> 8) | (((x) &0xff00) << 8) | ((x) << 24))
|
|
||||||
|
|
||||||
#if !defined(WEAK)
|
|
||||||
#if (defined(__GNUC__) || defined(__clang__) || \
|
|
||||||
defined(__TI_COMPILER_VERSION__)) && \
|
|
||||||
!defined(_WIN32) && !defined(__CYGWIN__)
|
|
||||||
#define WEAK __attribute__((weak))
|
|
||||||
#else
|
|
||||||
#define WEAK
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Expands to a string representation of its argument: e.g.
|
// Expands to a string representation of its argument: e.g.
|
||||||
// MG_STRINGIFY_LITERAL(5) expands to "5"
|
// MG_STRINGIFY_LITERAL(5) expands to "5"
|
||||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||||
@@ -58,7 +56,12 @@ FILE *mg_fopen(const char *fp, const char *mode);
|
|||||||
#else
|
#else
|
||||||
#define MG_STRINGIFY_LITERAL(x) #x
|
#define MG_STRINGIFY_LITERAL(x) #x
|
||||||
#endif
|
#endif
|
||||||
|
// Expands to a string representation of its argument, which can be a macro:
|
||||||
|
// #define FOO 123
|
||||||
|
// MG_STRINGIFY_MACRO(FOO) // Expands to 123
|
||||||
|
#define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
|
||||||
|
|
||||||
|
// Linked list management macros
|
||||||
#define LIST_ADD_HEAD(type_, head_, elem_) \
|
#define LIST_ADD_HEAD(type_, head_, elem_) \
|
||||||
do { \
|
do { \
|
||||||
(elem_)->next = (*head_); \
|
(elem_)->next = (*head_); \
|
||||||
@@ -78,8 +81,3 @@ FILE *mg_fopen(const char *fp, const char *mode);
|
|||||||
while (*h != (elem_)) h = &(*h)->next; \
|
while (*h != (elem_)) h = &(*h)->next; \
|
||||||
*h = (elem_)->next; \
|
*h = (elem_)->next; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Expands to a string representation of its argument, which can be a macro:
|
|
||||||
// #define FOO 123
|
|
||||||
// MG_STRINGIFY_MACRO(FOO) // Expands to 123
|
|
||||||
#define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
|
|
||||||
+9
-2
@@ -1,2 +1,9 @@
|
|||||||
#pragma once
|
|
||||||
#define MG_VERSION "7.2"
|
#ifndef MONGOOSE_H
|
||||||
|
#define MONGOOSE_H
|
||||||
|
|
||||||
|
#define MG_VERSION "7.3"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
@@ -54,7 +54,7 @@ static size_t ws_process(uint8_t *buf, size_t len, struct ws_msg *msg) {
|
|||||||
} else if (len >= 10 + mask_len) {
|
} else if (len >= 10 + mask_len) {
|
||||||
msg->header_len = 10 + mask_len;
|
msg->header_len = 10 + mask_len;
|
||||||
msg->data_len =
|
msg->data_len =
|
||||||
(int) (((uint64_t) mg_ntohl(*(uint32_t *) &buf[2])) << 32) +
|
(size_t)(((uint64_t) mg_ntohl(*(uint32_t *) &buf[2])) << 32) +
|
||||||
mg_ntohl(*(uint32_t *) &buf[6]);
|
mg_ntohl(*(uint32_t *) &buf[6]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
|
|||||||
c->is_websocket = 1;
|
c->is_websocket = 1;
|
||||||
mg_call(c, MG_EV_WS_OPEN, &hm);
|
mg_call(c, MG_EV_WS_OPEN, &hm);
|
||||||
}
|
}
|
||||||
mg_iobuf_delete(&c->recv, n);
|
mg_iobuf_delete(&c->recv, (size_t) n);
|
||||||
} else {
|
} else {
|
||||||
return; // A request is not yet received
|
return; // A request is not yet received
|
||||||
}
|
}
|
||||||
@@ -134,6 +134,9 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
|
|||||||
char *s = (char *) c->recv.buf + msg.header_len;
|
char *s = (char *) c->recv.buf + msg.header_len;
|
||||||
struct mg_ws_message m = {{s, msg.data_len}, msg.flags};
|
struct mg_ws_message m = {{s, msg.data_len}, msg.flags};
|
||||||
switch (msg.flags & WEBSOCKET_FLAGS_MASK_OP) {
|
switch (msg.flags & WEBSOCKET_FLAGS_MASK_OP) {
|
||||||
|
case WEBSOCKET_OP_CONTINUE:
|
||||||
|
mg_call(c, MG_EV_WS_CTL, &m);
|
||||||
|
break;
|
||||||
case WEBSOCKET_OP_PING:
|
case WEBSOCKET_OP_PING:
|
||||||
LOG(LL_DEBUG, ("%s", "WS PONG"));
|
LOG(LL_DEBUG, ("%s", "WS PONG"));
|
||||||
mg_ws_send(c, s, msg.data_len, WEBSOCKET_OP_PONG);
|
mg_ws_send(c, s, msg.data_len, WEBSOCKET_OP_PONG);
|
||||||
@@ -142,15 +145,19 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
|
|||||||
case WEBSOCKET_OP_PONG:
|
case WEBSOCKET_OP_PONG:
|
||||||
mg_call(c, MG_EV_WS_CTL, &m);
|
mg_call(c, MG_EV_WS_CTL, &m);
|
||||||
break;
|
break;
|
||||||
|
case WEBSOCKET_OP_TEXT:
|
||||||
|
case WEBSOCKET_OP_BINARY:
|
||||||
|
mg_call(c, MG_EV_WS_MSG, &m);
|
||||||
|
break;
|
||||||
case WEBSOCKET_OP_CLOSE:
|
case WEBSOCKET_OP_CLOSE:
|
||||||
LOG(LL_ERROR, ("%lu Got WS CLOSE", c->id));
|
LOG(LL_ERROR, ("%lu Got WS CLOSE", c->id));
|
||||||
mg_call(c, MG_EV_WS_CTL, &m);
|
mg_call(c, MG_EV_WS_CTL, &m);
|
||||||
c->is_closing = 1;
|
c->is_closing = 1;
|
||||||
return;
|
|
||||||
default: {
|
|
||||||
mg_call(c, MG_EV_WS_MSG, &m);
|
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
// Per RFC6455, close conn when an unknown op is recvd
|
||||||
|
mg_error(c, "unknown WS op %d", msg.flags & WEBSOCKET_FLAGS_MASK_OP);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
mg_iobuf_delete(&c->recv, msg.header_len + msg.data_len);
|
mg_iobuf_delete(&c->recv, msg.header_len + msg.data_len);
|
||||||
}
|
}
|
||||||
@@ -188,7 +195,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
|
|||||||
"Sec-WebSocket-Key: %s\r\n"
|
"Sec-WebSocket-Key: %s\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key);
|
mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key);
|
||||||
mg_send(c, buf2, n2);
|
mg_send(c, buf2, n2 > 0 ? (size_t) n2 : 0);
|
||||||
if (buf1 != mem1) free(buf1);
|
if (buf1 != mem1) free(buf1);
|
||||||
if (buf2 != mem2) free(buf2);
|
if (buf2 != mem2) free(buf2);
|
||||||
c->pfn = mg_ws_cb;
|
c->pfn = mg_ws_cb;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
secret
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
є
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "croutine.h"
|
||||||
|
|
||||||
|
/* Remove the whole file is co-routines are not being used. */
|
||||||
|
#if ( configUSE_CO_ROUTINES != 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||||
|
* than file scope.
|
||||||
|
*/
|
||||||
|
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||||
|
#define static
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Lists for ready and blocked co-routines. --------------------*/
|
||||||
|
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
|
||||||
|
static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
|
||||||
|
static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
|
||||||
|
static List_t * pxDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used. */
|
||||||
|
static List_t * pxOverflowDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
|
||||||
|
static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
|
||||||
|
|
||||||
|
/* Other file private variables. --------------------------------*/
|
||||||
|
CRCB_t * pxCurrentCoRoutine = NULL;
|
||||||
|
static UBaseType_t uxTopCoRoutineReadyPriority = 0;
|
||||||
|
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
|
||||||
|
|
||||||
|
/* The initial state of the co-routine when it is created. */
|
||||||
|
#define corINITIAL_STATE ( 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Place the co-routine represented by pxCRCB into the appropriate ready queue
|
||||||
|
* for the priority. It is inserted at the end of the list.
|
||||||
|
*
|
||||||
|
* This macro accesses the co-routine ready lists and therefore must not be
|
||||||
|
* used from within an ISR.
|
||||||
|
*/
|
||||||
|
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
|
||||||
|
{ \
|
||||||
|
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
|
||||||
|
{ \
|
||||||
|
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
|
||||||
|
} \
|
||||||
|
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility to ready all the lists used by the scheduler. This is called
|
||||||
|
* automatically upon the creation of the first co-routine.
|
||||||
|
*/
|
||||||
|
static void prvInitialiseCoRoutineLists( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Co-routines that are readied by an interrupt cannot be placed directly into
|
||||||
|
* the ready lists (there is no mutual exclusion). Instead they are placed in
|
||||||
|
* in the pending ready list in order that they can later be moved to the ready
|
||||||
|
* list by the co-routine scheduler.
|
||||||
|
*/
|
||||||
|
static void prvCheckPendingReadyList( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro that looks at the list of co-routines that are currently delayed to
|
||||||
|
* see if any require waking.
|
||||||
|
*
|
||||||
|
* Co-routines are stored in the queue in the order of their wake time -
|
||||||
|
* meaning once one co-routine has been found whose timer has not expired
|
||||||
|
* we need not look any further down the list.
|
||||||
|
*/
|
||||||
|
static void prvCheckDelayedList( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
UBaseType_t uxIndex )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
CRCB_t * pxCoRoutine;
|
||||||
|
|
||||||
|
/* Allocate the memory that will store the co-routine control block. */
|
||||||
|
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
|
||||||
|
|
||||||
|
if( pxCoRoutine )
|
||||||
|
{
|
||||||
|
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
|
||||||
|
* be created and the co-routine data structures need initialising. */
|
||||||
|
if( pxCurrentCoRoutine == NULL )
|
||||||
|
{
|
||||||
|
pxCurrentCoRoutine = pxCoRoutine;
|
||||||
|
prvInitialiseCoRoutineLists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the priority is within limits. */
|
||||||
|
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
|
||||||
|
{
|
||||||
|
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill out the co-routine control block from the function parameters. */
|
||||||
|
pxCoRoutine->uxState = corINITIAL_STATE;
|
||||||
|
pxCoRoutine->uxPriority = uxPriority;
|
||||||
|
pxCoRoutine->uxIndex = uxIndex;
|
||||||
|
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
|
||||||
|
|
||||||
|
/* Initialise all the other co-routine control block parameters. */
|
||||||
|
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
|
||||||
|
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
|
||||||
|
|
||||||
|
/* Set the co-routine control block as a link back from the ListItem_t.
|
||||||
|
* This is so we can get back to the containing CRCB from a generic item
|
||||||
|
* in a list. */
|
||||||
|
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
|
||||||
|
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
|
||||||
|
|
||||||
|
/* Event lists are always in priority order. */
|
||||||
|
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
|
||||||
|
|
||||||
|
/* Now the co-routine has been initialised it can be added to the ready
|
||||||
|
* list at the correct priority. */
|
||||||
|
prvAddCoRoutineToReadyQueue( pxCoRoutine );
|
||||||
|
|
||||||
|
xReturn = pdPASS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
|
||||||
|
List_t * pxEventList )
|
||||||
|
{
|
||||||
|
TickType_t xTimeToWake;
|
||||||
|
|
||||||
|
/* Calculate the time to wake - this may overflow but this is
|
||||||
|
* not a problem. */
|
||||||
|
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
|
||||||
|
|
||||||
|
/* We must remove ourselves from the ready list before adding
|
||||||
|
* ourselves to the blocked list as the same list item is used for
|
||||||
|
* both lists. */
|
||||||
|
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||||
|
|
||||||
|
/* The list item will be inserted in wake time order. */
|
||||||
|
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
|
||||||
|
|
||||||
|
if( xTimeToWake < xCoRoutineTickCount )
|
||||||
|
{
|
||||||
|
/* Wake time has overflowed. Place this item in the
|
||||||
|
* overflow list. */
|
||||||
|
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The wake time has not overflowed, so we can use the
|
||||||
|
* current block list. */
|
||||||
|
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pxEventList )
|
||||||
|
{
|
||||||
|
/* Also add the co-routine to an event list. If this is done then the
|
||||||
|
* function must be called with interrupts disabled. */
|
||||||
|
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckPendingReadyList( void )
|
||||||
|
{
|
||||||
|
/* Are there any co-routines waiting to get moved to the ready list? These
|
||||||
|
* are co-routines that have been readied by an ISR. The ISR cannot access
|
||||||
|
* the ready lists itself. */
|
||||||
|
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
|
||||||
|
{
|
||||||
|
CRCB_t * pxUnblockedCRCB;
|
||||||
|
|
||||||
|
/* The pending ready list can be accessed by an ISR. */
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
{
|
||||||
|
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
|
||||||
|
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||||
|
}
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
|
||||||
|
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckDelayedList( void )
|
||||||
|
{
|
||||||
|
CRCB_t * pxCRCB;
|
||||||
|
|
||||||
|
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
|
||||||
|
|
||||||
|
while( xPassedTicks )
|
||||||
|
{
|
||||||
|
xCoRoutineTickCount++;
|
||||||
|
xPassedTicks--;
|
||||||
|
|
||||||
|
/* If the tick count has overflowed we need to swap the ready lists. */
|
||||||
|
if( xCoRoutineTickCount == 0 )
|
||||||
|
{
|
||||||
|
List_t * pxTemp;
|
||||||
|
|
||||||
|
/* Tick count has overflowed so we need to swap the delay lists. If there are
|
||||||
|
* any items in pxDelayedCoRoutineList here then there is an error! */
|
||||||
|
pxTemp = pxDelayedCoRoutineList;
|
||||||
|
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
|
||||||
|
pxOverflowDelayedCoRoutineList = pxTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if this tick has made a timeout expire. */
|
||||||
|
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
|
||||||
|
{
|
||||||
|
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
|
||||||
|
|
||||||
|
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
|
||||||
|
{
|
||||||
|
/* Timeout not yet expired. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
{
|
||||||
|
/* The event could have occurred just before this critical
|
||||||
|
* section. If this is the case then the generic list item will
|
||||||
|
* have been moved to the pending ready list and the following
|
||||||
|
* line is still valid. Also the pvContainer parameter will have
|
||||||
|
* been set to NULL so the following lines are also valid. */
|
||||||
|
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
|
||||||
|
|
||||||
|
/* Is the co-routine waiting on an event also? */
|
||||||
|
if( pxCRCB->xEventListItem.pxContainer )
|
||||||
|
{
|
||||||
|
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
prvAddCoRoutineToReadyQueue( pxCRCB );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xLastTickCount = xCoRoutineTickCount;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCoRoutineSchedule( void )
|
||||||
|
{
|
||||||
|
/* Only run a co-routine after prvInitialiseCoRoutineLists() has been
|
||||||
|
* called. prvInitialiseCoRoutineLists() is called automatically when a
|
||||||
|
* co-routine is created. */
|
||||||
|
if( pxDelayedCoRoutineList != NULL )
|
||||||
|
{
|
||||||
|
/* See if any co-routines readied by events need moving to the ready lists. */
|
||||||
|
prvCheckPendingReadyList();
|
||||||
|
|
||||||
|
/* See if any delayed co-routines have timed out. */
|
||||||
|
prvCheckDelayedList();
|
||||||
|
|
||||||
|
/* Find the highest priority queue that contains ready co-routines. */
|
||||||
|
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
|
||||||
|
{
|
||||||
|
if( uxTopCoRoutineReadyPriority == 0 )
|
||||||
|
{
|
||||||
|
/* No more co-routines to check. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
--uxTopCoRoutineReadyPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
|
||||||
|
* of the same priority get an equal share of the processor time. */
|
||||||
|
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
|
||||||
|
|
||||||
|
/* Call the co-routine. */
|
||||||
|
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvInitialiseCoRoutineLists( void )
|
||||||
|
{
|
||||||
|
UBaseType_t uxPriority;
|
||||||
|
|
||||||
|
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
|
||||||
|
{
|
||||||
|
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
|
||||||
|
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
|
||||||
|
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
|
||||||
|
|
||||||
|
/* Start with pxDelayedCoRoutineList using list1 and the
|
||||||
|
* pxOverflowDelayedCoRoutineList using list2. */
|
||||||
|
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
|
||||||
|
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
|
||||||
|
{
|
||||||
|
CRCB_t * pxUnblockedCRCB;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* This function is called from within an interrupt. It can only access
|
||||||
|
* event lists and the pending ready list. This function assumes that a
|
||||||
|
* check has already been made to ensure pxEventList is not empty. */
|
||||||
|
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||||
|
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||||
|
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
|
||||||
|
|
||||||
|
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_CO_ROUTINES == 0 */
|
||||||
@@ -0,0 +1,771 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
* all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
* task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "timers.h"
|
||||||
|
#include "event_groups.h"
|
||||||
|
|
||||||
|
/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
|
||||||
|
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
|
||||||
|
* for the header files above, but not in this file, in order to generate the
|
||||||
|
* correct privileged Vs unprivileged linkage and placement. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
|
||||||
|
|
||||||
|
/* The following bit fields convey control information in a task's event list
|
||||||
|
* item value. It is important they don't clash with the
|
||||||
|
* taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
|
||||||
|
#if configUSE_16_BIT_TICKS == 1
|
||||||
|
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
|
||||||
|
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
|
||||||
|
#define eventWAIT_FOR_ALL_BITS 0x0400U
|
||||||
|
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
|
||||||
|
#else
|
||||||
|
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
|
||||||
|
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
|
||||||
|
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
|
||||||
|
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct EventGroupDef_t
|
||||||
|
{
|
||||||
|
EventBits_t uxEventBits;
|
||||||
|
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
UBaseType_t uxEventGroupNumber;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||||
|
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
|
||||||
|
#endif
|
||||||
|
} EventGroup_t;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
|
||||||
|
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
|
||||||
|
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
|
||||||
|
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
|
||||||
|
* wait condition is met if any of the bits set in uxBitsToWait for are also set
|
||||||
|
* in uxCurrentEventBits.
|
||||||
|
*/
|
||||||
|
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
|
||||||
|
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits;
|
||||||
|
|
||||||
|
/* A StaticEventGroup_t object must be provided. */
|
||||||
|
configASSERT( pxEventGroupBuffer );
|
||||||
|
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
/* Sanity check that the size of the structure used to declare a
|
||||||
|
* variable of type StaticEventGroup_t equals the size of the real
|
||||||
|
* event group structure. */
|
||||||
|
volatile size_t xSize = sizeof( StaticEventGroup_t );
|
||||||
|
configASSERT( xSize == sizeof( EventGroup_t ) );
|
||||||
|
} /*lint !e529 xSize is referenced if configASSERT() is defined. */
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* The user has provided a statically allocated event group - use it. */
|
||||||
|
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
|
||||||
|
|
||||||
|
if( pxEventBits != NULL )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits = 0;
|
||||||
|
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||||
|
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
{
|
||||||
|
/* Both static and dynamic allocation can be used, so note that
|
||||||
|
* this event group was created statically in case the event group
|
||||||
|
* is later deleted. */
|
||||||
|
pxEventBits->ucStaticallyAllocated = pdTRUE;
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
|
||||||
|
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* xEventGroupCreateStatic should only ever be called with
|
||||||
|
* pxEventGroupBuffer pointing to a pre-allocated (compile time
|
||||||
|
* allocated) StaticEventGroup_t variable. */
|
||||||
|
traceEVENT_GROUP_CREATE_FAILED();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxEventBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
|
||||||
|
EventGroupHandle_t xEventGroupCreate( void )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits;
|
||||||
|
|
||||||
|
/* Allocate the event group. Justification for MISRA deviation as
|
||||||
|
* follows: pvPortMalloc() always ensures returned memory blocks are
|
||||||
|
* aligned per the requirements of the MCU stack. In this case
|
||||||
|
* pvPortMalloc() must return a pointer that is guaranteed to meet the
|
||||||
|
* alignment requirements of the EventGroup_t structure - which (if you
|
||||||
|
* follow it through) is the alignment requirements of the TickType_t type
|
||||||
|
* (EventBits_t being of TickType_t itself). Therefore, whenever the
|
||||||
|
* stack alignment requirements are greater than or equal to the
|
||||||
|
* TickType_t alignment requirements the cast is safe. In other cases,
|
||||||
|
* where the natural word size of the architecture is less than
|
||||||
|
* sizeof( TickType_t ), the TickType_t variables will be accessed in two
|
||||||
|
* or more reads operations, and the alignment requirements is only that
|
||||||
|
* of each individual read. */
|
||||||
|
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
|
||||||
|
|
||||||
|
if( pxEventBits != NULL )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits = 0;
|
||||||
|
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||||
|
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
{
|
||||||
|
/* Both static and dynamic allocation can be used, so note this
|
||||||
|
* event group was allocated statically in case the event group is
|
||||||
|
* later deleted. */
|
||||||
|
pxEventBits->ucStaticallyAllocated = pdFALSE;
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
|
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxEventBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
TickType_t xTicksToWait )
|
||||||
|
{
|
||||||
|
EventBits_t uxOriginalBitValue, uxReturn;
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
BaseType_t xAlreadyYielded;
|
||||||
|
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||||
|
|
||||||
|
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
configASSERT( uxBitsToWaitFor != 0 );
|
||||||
|
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||||
|
{
|
||||||
|
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
uxOriginalBitValue = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
|
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||||
|
{
|
||||||
|
/* All the rendezvous bits are now set - no need to block. */
|
||||||
|
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
|
||||||
|
|
||||||
|
/* Rendezvous always clear the bits. They will have been cleared
|
||||||
|
* already unless this is the only task in the rendezvous. */
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
|
||||||
|
xTicksToWait = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( xTicksToWait != ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
|
||||||
|
|
||||||
|
/* Store the bits that the calling task is waiting for in the
|
||||||
|
* task's event list item so the kernel knows when a match is
|
||||||
|
* found. Then enter the blocked state. */
|
||||||
|
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
|
||||||
|
|
||||||
|
/* This assignment is obsolete as uxReturn will get set after
|
||||||
|
* the task unblocks, but some compilers mistakenly generate a
|
||||||
|
* warning about uxReturn being returned without being set if the
|
||||||
|
* assignment is omitted. */
|
||||||
|
uxReturn = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The rendezvous bits were not set, but no block time was
|
||||||
|
* specified - just return the current event bit value. */
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xAlreadyYielded = xTaskResumeAll();
|
||||||
|
|
||||||
|
if( xTicksToWait != ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
if( xAlreadyYielded == pdFALSE )
|
||||||
|
{
|
||||||
|
portYIELD_WITHIN_API();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task blocked to wait for its required bits to be set - at this
|
||||||
|
* point either the required bits were set or the block time expired. If
|
||||||
|
* the required bits were set they will have been stored in the task's
|
||||||
|
* event list item, and they should now be retrieved then cleared. */
|
||||||
|
uxReturn = uxTaskResetEventItemValue();
|
||||||
|
|
||||||
|
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
/* The task timed out, just return the current event bit value. */
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* Although the task got here because it timed out before the
|
||||||
|
* bits it was waiting for were set, it is possible that since it
|
||||||
|
* unblocked another task has set the bits. If this is the case
|
||||||
|
* then it needs to clear the bits before exiting. */
|
||||||
|
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task unblocked because the bits were set. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Control bits might be set as the task had blocked should not be
|
||||||
|
* returned. */
|
||||||
|
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
|
||||||
|
|
||||||
|
/* Prevent compiler warnings when trace macros are not used. */
|
||||||
|
( void ) xTimeoutOccurred;
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
EventBits_t uxReturn, uxControlBits = 0;
|
||||||
|
BaseType_t xWaitConditionMet, xAlreadyYielded;
|
||||||
|
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||||
|
|
||||||
|
/* Check the user is not attempting to wait on the bits used by the kernel
|
||||||
|
* itself, and that at least one bit is being requested. */
|
||||||
|
configASSERT( xEventGroup );
|
||||||
|
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
configASSERT( uxBitsToWaitFor != 0 );
|
||||||
|
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||||
|
{
|
||||||
|
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* Check to see if the wait condition is already met or not. */
|
||||||
|
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
|
||||||
|
|
||||||
|
if( xWaitConditionMet != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The wait condition has already been met so there is no need to
|
||||||
|
* block. */
|
||||||
|
uxReturn = uxCurrentEventBits;
|
||||||
|
xTicksToWait = ( TickType_t ) 0;
|
||||||
|
|
||||||
|
/* Clear the wait bits if requested to do so. */
|
||||||
|
if( xClearOnExit != pdFALSE )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( xTicksToWait == ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
/* The wait condition has not been met, but no block time was
|
||||||
|
* specified, so just return the current value. */
|
||||||
|
uxReturn = uxCurrentEventBits;
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task is going to block to wait for its required bits to be
|
||||||
|
* set. uxControlBits are used to remember the specified behaviour of
|
||||||
|
* this call to xEventGroupWaitBits() - for use when the event bits
|
||||||
|
* unblock the task. */
|
||||||
|
if( xClearOnExit != pdFALSE )
|
||||||
|
{
|
||||||
|
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xWaitForAllBits != pdFALSE )
|
||||||
|
{
|
||||||
|
uxControlBits |= eventWAIT_FOR_ALL_BITS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the bits that the calling task is waiting for in the
|
||||||
|
* task's event list item so the kernel knows when a match is
|
||||||
|
* found. Then enter the blocked state. */
|
||||||
|
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
||||||
|
|
||||||
|
/* This is obsolete as it will get set after the task unblocks, but
|
||||||
|
* some compilers mistakenly generate a warning about the variable
|
||||||
|
* being returned without being set if it is not done. */
|
||||||
|
uxReturn = 0;
|
||||||
|
|
||||||
|
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xAlreadyYielded = xTaskResumeAll();
|
||||||
|
|
||||||
|
if( xTicksToWait != ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
if( xAlreadyYielded == pdFALSE )
|
||||||
|
{
|
||||||
|
portYIELD_WITHIN_API();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task blocked to wait for its required bits to be set - at this
|
||||||
|
* point either the required bits were set or the block time expired. If
|
||||||
|
* the required bits were set they will have been stored in the task's
|
||||||
|
* event list item, and they should now be retrieved then cleared. */
|
||||||
|
uxReturn = uxTaskResetEventItemValue();
|
||||||
|
|
||||||
|
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
/* The task timed out, just return the current event bit value. */
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* It is possible that the event bits were updated between this
|
||||||
|
* task leaving the Blocked state and running again. */
|
||||||
|
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
|
||||||
|
{
|
||||||
|
if( xClearOnExit != pdFALSE )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task unblocked because the bits were set. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task blocked so control bits may have been set. */
|
||||||
|
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
|
||||||
|
|
||||||
|
/* Prevent compiler warnings when trace macros are not used. */
|
||||||
|
( void ) xTimeoutOccurred;
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
EventBits_t uxReturn;
|
||||||
|
|
||||||
|
/* Check the user is not attempting to clear the bits used by the kernel
|
||||||
|
* itself. */
|
||||||
|
configASSERT( xEventGroup );
|
||||||
|
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
|
||||||
|
|
||||||
|
/* The value returned is the event group value prior to the bits being
|
||||||
|
* cleared. */
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* Clear the bits. */
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||||
|
|
||||||
|
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
|
||||||
|
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
|
||||||
|
{
|
||||||
|
UBaseType_t uxSavedInterruptStatus;
|
||||||
|
EventGroup_t const * const pxEventBits = xEventGroup;
|
||||||
|
EventBits_t uxReturn;
|
||||||
|
|
||||||
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet )
|
||||||
|
{
|
||||||
|
ListItem_t * pxListItem, * pxNext;
|
||||||
|
ListItem_t const * pxListEnd;
|
||||||
|
List_t const * pxList;
|
||||||
|
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
BaseType_t xMatchFound = pdFALSE;
|
||||||
|
|
||||||
|
/* Check the user is not attempting to set the bits used by the kernel
|
||||||
|
* itself. */
|
||||||
|
configASSERT( xEventGroup );
|
||||||
|
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
|
||||||
|
pxList = &( pxEventBits->xTasksWaitingForBits );
|
||||||
|
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
|
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||||
|
|
||||||
|
/* Set the bits. */
|
||||||
|
pxEventBits->uxEventBits |= uxBitsToSet;
|
||||||
|
|
||||||
|
/* See if the new bit value should unblock any tasks. */
|
||||||
|
while( pxListItem != pxListEnd )
|
||||||
|
{
|
||||||
|
pxNext = listGET_NEXT( pxListItem );
|
||||||
|
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
|
||||||
|
xMatchFound = pdFALSE;
|
||||||
|
|
||||||
|
/* Split the bits waited for from the control bits. */
|
||||||
|
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
|
||||||
|
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
/* Just looking for single bit being set. */
|
||||||
|
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
xMatchFound = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
|
||||||
|
{
|
||||||
|
/* All bits are set. */
|
||||||
|
xMatchFound = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Need all bits to be set, but not all the bits were set. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xMatchFound != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The bits match. Should the bits be cleared on exit? */
|
||||||
|
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
uxBitsToClear |= uxBitsWaitedFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the actual event flag value in the task's event list
|
||||||
|
* item before removing the task from the event list. The
|
||||||
|
* eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
|
||||||
|
* that is was unblocked due to its required bits matching, rather
|
||||||
|
* than because it timed out. */
|
||||||
|
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move onto the next list item. Note pxListItem->pxNext is not
|
||||||
|
* used here as the list item may have been removed from the event list
|
||||||
|
* and inserted into the ready/pending reading list. */
|
||||||
|
pxListItem = pxNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
|
||||||
|
* bit was set in the control word. */
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
return pxEventBits->uxEventBits;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_DELETE( xEventGroup );
|
||||||
|
|
||||||
|
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
|
||||||
|
{
|
||||||
|
/* Unblock the task, returning 0 as the event list is being deleted
|
||||||
|
* and cannot therefore have any bits set. */
|
||||||
|
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||||
|
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||||
|
{
|
||||||
|
/* The event group can only have been allocated dynamically - free
|
||||||
|
* it again. */
|
||||||
|
vPortFree( pxEventBits );
|
||||||
|
}
|
||||||
|
#elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||||
|
{
|
||||||
|
/* The event group could have been allocated statically or
|
||||||
|
* dynamically, so check before attempting to free the memory. */
|
||||||
|
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
|
||||||
|
{
|
||||||
|
vPortFree( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* For internal use only - execute a 'set bits' command that was pended from
|
||||||
|
* an interrupt. */
|
||||||
|
void vEventGroupSetBitsCallback( void * pvEventGroup,
|
||||||
|
const uint32_t ulBitsToSet )
|
||||||
|
{
|
||||||
|
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* For internal use only - execute a 'clear bits' command that was pended from
|
||||||
|
* an interrupt. */
|
||||||
|
void vEventGroupClearBitsCallback( void * pvEventGroup,
|
||||||
|
const uint32_t ulBitsToClear )
|
||||||
|
{
|
||||||
|
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xWaitForAllBits )
|
||||||
|
{
|
||||||
|
BaseType_t xWaitConditionMet = pdFALSE;
|
||||||
|
|
||||||
|
if( xWaitForAllBits == pdFALSE )
|
||||||
|
{
|
||||||
|
/* Task only has to wait for one bit within uxBitsToWaitFor to be
|
||||||
|
* set. Is one already set? */
|
||||||
|
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
xWaitConditionMet = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
|
||||||
|
* Are they set already? */
|
||||||
|
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||||
|
{
|
||||||
|
xWaitConditionMet = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return xWaitConditionMet;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||||
|
|
||||||
|
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
|
||||||
|
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
|
UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
|
||||||
|
{
|
||||||
|
UBaseType_t xReturn;
|
||||||
|
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
|
||||||
|
|
||||||
|
if( xEventGroup == NULL )
|
||||||
|
{
|
||||||
|
xReturn = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pxEventBits->uxEventGroupNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TRACE_FACILITY */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
|
void vEventGroupSetNumber( void * xEventGroup,
|
||||||
|
UBaseType_t uxEventGroupNumber )
|
||||||
|
{
|
||||||
|
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TRACE_FACILITY */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
|
||||||
|
#warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "stack_macros.h"
|
||||||
@@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file atomic.h
|
||||||
|
* @brief FreeRTOS atomic operation support.
|
||||||
|
*
|
||||||
|
* This file implements atomic functions by disabling interrupts globally.
|
||||||
|
* Implementations with architecture specific atomic instructions can be
|
||||||
|
* provided under each compiler directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ATOMIC_H
|
||||||
|
#define ATOMIC_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h must appear in source files before include atomic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port specific definitions -- entering/exiting critical section.
|
||||||
|
* Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
|
||||||
|
*
|
||||||
|
* Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
|
||||||
|
* ATOMIC_ENTER_CRITICAL().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
|
||||||
|
|
||||||
|
/* Nested interrupt scheme is supported in this port. */
|
||||||
|
#define ATOMIC_ENTER_CRITICAL() \
|
||||||
|
UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
|
||||||
|
|
||||||
|
#define ATOMIC_EXIT_CRITICAL() \
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Nested interrupt scheme is NOT supported in this port. */
|
||||||
|
#define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
|
||||||
|
#define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
|
||||||
|
|
||||||
|
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port specific definition -- "always inline".
|
||||||
|
* Inline is compiler specific, and may not always get inlined depending on your
|
||||||
|
* optimization level. Also, inline is considered as performance optimization
|
||||||
|
* for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
|
||||||
|
* instead of resulting error, simply define it away.
|
||||||
|
*/
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */
|
||||||
|
#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
|
||||||
|
|
||||||
|
/*----------------------------- Swap && CAS ------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic compare-and-swap
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic compare-and-swap operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param[in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and checked.
|
||||||
|
* @param[in] ulExchange If condition meets, write this value to memory.
|
||||||
|
* @param[in] ulComparand Swap condition.
|
||||||
|
*
|
||||||
|
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||||
|
*
|
||||||
|
* @note This function only swaps *pulDestination with ulExchange, if previous
|
||||||
|
* *pulDestination value equals ulComparand.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulExchange,
|
||||||
|
uint32_t ulComparand )
|
||||||
|
{
|
||||||
|
uint32_t ulReturnValue;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( *pulDestination == ulComparand )
|
||||||
|
{
|
||||||
|
*pulDestination = ulExchange;
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulReturnValue;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic swap (pointers)
|
||||||
|
*
|
||||||
|
* @brief Atomically sets the address pointed to by *ppvDestination to the value
|
||||||
|
* of *pvExchange.
|
||||||
|
*
|
||||||
|
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||||
|
* value is to be loaded and written back to.
|
||||||
|
* @param[in] pvExchange Pointer value to be written to *ppvDestination.
|
||||||
|
*
|
||||||
|
* @return The initial value of *ppvDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
|
||||||
|
void * pvExchange )
|
||||||
|
{
|
||||||
|
void * pReturnValue;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
pReturnValue = *ppvDestination;
|
||||||
|
*ppvDestination = pvExchange;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return pReturnValue;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic compare-and-swap (pointers)
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic compare-and-swap operation on the specified pointer
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||||
|
* value is to be loaded and checked.
|
||||||
|
* @param[in] pvExchange If condition meets, write this value to memory.
|
||||||
|
* @param[in] pvComparand Swap condition.
|
||||||
|
*
|
||||||
|
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||||
|
*
|
||||||
|
* @note This function only swaps *ppvDestination with pvExchange, if previous
|
||||||
|
* *ppvDestination value equals pvComparand.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
|
||||||
|
void * pvExchange,
|
||||||
|
void * pvComparand )
|
||||||
|
{
|
||||||
|
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( *ppvDestination == pvComparand )
|
||||||
|
{
|
||||||
|
*ppvDestination = pvExchange;
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------- Arithmetic ------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic add
|
||||||
|
*
|
||||||
|
* @brief Atomically adds count to the value of the specified pointer points to.
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
* @param[in] ulCount Value to be added to *pulAddend.
|
||||||
|
*
|
||||||
|
* @return previous *pulAddend value.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
|
||||||
|
uint32_t ulCount )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend += ulCount;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic subtract
|
||||||
|
*
|
||||||
|
* @brief Atomically subtracts count from the value of the specified pointer
|
||||||
|
* pointers to.
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
* @param[in] ulCount Value to be subtract from *pulAddend.
|
||||||
|
*
|
||||||
|
* @return previous *pulAddend value.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
|
||||||
|
uint32_t ulCount )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend -= ulCount;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic increment
|
||||||
|
*
|
||||||
|
* @brief Atomically increments the value of the specified pointer points to.
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
*
|
||||||
|
* @return *pulAddend value before increment.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend += 1;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic decrement
|
||||||
|
*
|
||||||
|
* @brief Atomically decrements the value of the specified pointer points to
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
*
|
||||||
|
* @return *pulAddend value before decrement.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend -= 1;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------- Bitwise Logical ------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic OR
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic OR operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be ORed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination |= ulValue;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic AND
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic AND operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be ANDed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination &= ulValue;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic NAND
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic NAND operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be NANDed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination = ~( ulCurrent & ulValue );
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic XOR
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic XOR operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be XORed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination ^= ulValue;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* ATOMIC_H */
|
||||||
@@ -0,0 +1,751 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CO_ROUTINE_H
|
||||||
|
#define CO_ROUTINE_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h must appear in source files before include croutine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/* Used to hide the implementation of the co-routine control block. The
|
||||||
|
* control block structure however has to be included in the header due to
|
||||||
|
* the macro implementation of the co-routine functionality. */
|
||||||
|
typedef void * CoRoutineHandle_t;
|
||||||
|
|
||||||
|
/* Defines the prototype to which co-routine functions must conform. */
|
||||||
|
typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t,
|
||||||
|
UBaseType_t );
|
||||||
|
|
||||||
|
typedef struct corCoRoutineControlBlock
|
||||||
|
{
|
||||||
|
crCOROUTINE_CODE pxCoRoutineFunction;
|
||||||
|
ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
|
||||||
|
ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
|
||||||
|
UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
|
||||||
|
UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
|
||||||
|
uint16_t uxState; /*< Used internally by the co-routine implementation. */
|
||||||
|
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xCoRoutineCreate(
|
||||||
|
* crCOROUTINE_CODE pxCoRoutineCode,
|
||||||
|
* UBaseType_t uxPriority,
|
||||||
|
* UBaseType_t uxIndex
|
||||||
|
* );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Create a new co-routine and add it to the list of co-routines that are
|
||||||
|
* ready to run.
|
||||||
|
*
|
||||||
|
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
|
||||||
|
* functions require special syntax - see the co-routine section of the WEB
|
||||||
|
* documentation for more information.
|
||||||
|
*
|
||||||
|
* @param uxPriority The priority with respect to other co-routines at which
|
||||||
|
* the co-routine will run.
|
||||||
|
*
|
||||||
|
* @param uxIndex Used to distinguish between different co-routines that
|
||||||
|
* execute the same function. See the example below and the co-routine section
|
||||||
|
* of the WEB documentation for further information.
|
||||||
|
*
|
||||||
|
* @return pdPASS if the co-routine was successfully created and added to a ready
|
||||||
|
* list, otherwise an error code defined with ProjDefs.h.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* // This may not be necessary for const variables.
|
||||||
|
* static const char cLedToFlash[ 2 ] = { 5, 6 };
|
||||||
|
* static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // This co-routine just delays for a fixed period, then toggles
|
||||||
|
* // an LED. Two co-routines are created using this function, so
|
||||||
|
* // the uxIndex parameter is used to tell the co-routine which
|
||||||
|
* // LED to flash and how int32_t to delay. This assumes xQueue has
|
||||||
|
* // already been created.
|
||||||
|
* vParTestToggleLED( cLedToFlash[ uxIndex ] );
|
||||||
|
* crDELAY( xHandle, uxFlashRates[ uxIndex ] );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Function that creates two co-routines.
|
||||||
|
* void vOtherFunction( void )
|
||||||
|
* {
|
||||||
|
* uint8_t ucParameterToPass;
|
||||||
|
* TaskHandle_t xHandle;
|
||||||
|
*
|
||||||
|
* // Create two co-routines at priority 0. The first is given index 0
|
||||||
|
* // so (from the code above) toggles LED 5 every 200 ticks. The second
|
||||||
|
* // is given index 1 so toggles LED 6 every 400 ticks.
|
||||||
|
* for( uxIndex = 0; uxIndex < 2; uxIndex++ )
|
||||||
|
* {
|
||||||
|
* xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xCoRoutineCreate xCoRoutineCreate
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* void vCoRoutineSchedule( void );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Run a co-routine.
|
||||||
|
*
|
||||||
|
* vCoRoutineSchedule() executes the highest priority co-routine that is able
|
||||||
|
* to run. The co-routine will execute until it either blocks, yields or is
|
||||||
|
* preempted by a task. Co-routines execute cooperatively so one
|
||||||
|
* co-routine cannot be preempted by another, but can be preempted by a task.
|
||||||
|
*
|
||||||
|
* If an application comprises of both tasks and co-routines then
|
||||||
|
* vCoRoutineSchedule should be called from the idle task (in an idle task
|
||||||
|
* hook).
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // This idle task hook will schedule a co-routine each time it is called.
|
||||||
|
* // The rest of the idle task will execute between co-routine calls.
|
||||||
|
* void vApplicationIdleHook( void )
|
||||||
|
* {
|
||||||
|
* vCoRoutineSchedule();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Alternatively, if you do not require any other part of the idle task to
|
||||||
|
* // execute, the idle task hook can call vCoRoutineSchedule() within an
|
||||||
|
* // infinite loop.
|
||||||
|
* void vApplicationIdleHook( void )
|
||||||
|
* {
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* vCoRoutineSchedule();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
void vCoRoutineSchedule( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* crSTART( CoRoutineHandle_t xHandle );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* This macro MUST always be called at the start of a co-routine function.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static int32_t ulAVariable;
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Co-routine functionality goes here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crSTART crSTART
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crSTART( pxCRCB ) \
|
||||||
|
switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* crEND();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* This macro MUST always be called at the end of a co-routine function.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static int32_t ulAVariable;
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Co-routine functionality goes here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crSTART crSTART
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crEND() }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These macros are intended for internal use by the co-routine implementation
|
||||||
|
* only. The macros should not be used directly by application writers.
|
||||||
|
*/
|
||||||
|
#define crSET_STATE0( xHandle ) \
|
||||||
|
( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \
|
||||||
|
case ( __LINE__ * 2 ):
|
||||||
|
#define crSET_STATE1( xHandle ) \
|
||||||
|
( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \
|
||||||
|
case ( ( __LINE__ * 2 ) + 1 ):
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Delay a co-routine for a fixed period of time.
|
||||||
|
*
|
||||||
|
* crDELAY can only be called from the co-routine function itself - not
|
||||||
|
* from within a function called by the co-routine function. This is because
|
||||||
|
* co-routines do not maintain their own stack.
|
||||||
|
*
|
||||||
|
* @param xHandle The handle of the co-routine to delay. This is the xHandle
|
||||||
|
* parameter of the co-routine function.
|
||||||
|
*
|
||||||
|
* @param xTickToDelay The number of ticks that the co-routine should delay
|
||||||
|
* for. The actual amount of time this equates to is defined by
|
||||||
|
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
|
||||||
|
* can be used to convert ticks to milliseconds.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* // This may not be necessary for const variables.
|
||||||
|
* // We are to delay for 200ms.
|
||||||
|
* static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Delay for 200ms.
|
||||||
|
* crDELAY( xHandle, xDelayTime );
|
||||||
|
*
|
||||||
|
* // Do something here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crDELAY crDELAY
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crDELAY( xHandle, xTicksToDelay ) \
|
||||||
|
if( ( xTicksToDelay ) > 0 ) \
|
||||||
|
{ \
|
||||||
|
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
|
||||||
|
} \
|
||||||
|
crSET_STATE0( ( xHandle ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* crQUEUE_SEND(
|
||||||
|
* CoRoutineHandle_t xHandle,
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvItemToQueue,
|
||||||
|
* TickType_t xTicksToWait,
|
||||||
|
* BaseType_t *pxResult
|
||||||
|
* )
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||||
|
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||||
|
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND can only be called from the co-routine function itself - not
|
||||||
|
* from within a function called by the co-routine function. This is because
|
||||||
|
* co-routines do not maintain their own stack.
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||||
|
* parameter of the co-routine function.
|
||||||
|
*
|
||||||
|
* @param pxQueue The handle of the queue on which the data will be posted.
|
||||||
|
* The handle is obtained as the return value when the queue is created using
|
||||||
|
* the xQueueCreate() API function.
|
||||||
|
*
|
||||||
|
* @param pvItemToQueue A pointer to the data being posted onto the queue.
|
||||||
|
* The number of bytes of each queued item is specified when the queue is
|
||||||
|
* created. This number of bytes is copied from pvItemToQueue into the queue
|
||||||
|
* itself.
|
||||||
|
*
|
||||||
|
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||||
|
* to wait for space to become available on the queue, should space not be
|
||||||
|
* available immediately. The actual amount of time this equates to is defined
|
||||||
|
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||||
|
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
|
||||||
|
* below).
|
||||||
|
*
|
||||||
|
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||||
|
* data was successfully posted onto the queue, otherwise it will be set to an
|
||||||
|
* error defined within ProjDefs.h.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Co-routine function that blocks for a fixed period then posts a number onto
|
||||||
|
* // a queue.
|
||||||
|
* static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static BaseType_t xNumberToPost = 0;
|
||||||
|
* static BaseType_t xResult;
|
||||||
|
*
|
||||||
|
* // Co-routines must begin with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // This assumes the queue has already been created.
|
||||||
|
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* if( xResult != pdPASS )
|
||||||
|
* {
|
||||||
|
* // The message was not posted!
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Increment the number to be posted onto the queue.
|
||||||
|
* xNumberToPost++;
|
||||||
|
*
|
||||||
|
* // Delay for 100 ticks.
|
||||||
|
* crDELAY( xHandle, 100 );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Co-routines must end with a call to crEND().
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crQUEUE_SEND crQUEUE_SEND
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
|
||||||
|
{ \
|
||||||
|
*( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \
|
||||||
|
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE0( ( xHandle ) ); \
|
||||||
|
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
|
||||||
|
} \
|
||||||
|
if( *pxResult == errQUEUE_YIELD ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE1( ( xHandle ) ); \
|
||||||
|
*pxResult = pdPASS; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* crQUEUE_RECEIVE(
|
||||||
|
* CoRoutineHandle_t xHandle,
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvBuffer,
|
||||||
|
* TickType_t xTicksToWait,
|
||||||
|
* BaseType_t *pxResult
|
||||||
|
* )
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||||
|
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||||
|
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
|
||||||
|
* from within a function called by the co-routine function. This is because
|
||||||
|
* co-routines do not maintain their own stack.
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||||
|
* parameter of the co-routine function.
|
||||||
|
*
|
||||||
|
* @param pxQueue The handle of the queue from which the data will be received.
|
||||||
|
* The handle is obtained as the return value when the queue is created using
|
||||||
|
* the xQueueCreate() API function.
|
||||||
|
*
|
||||||
|
* @param pvBuffer The buffer into which the received item is to be copied.
|
||||||
|
* The number of bytes of each queued item is specified when the queue is
|
||||||
|
* created. This number of bytes is copied into pvBuffer.
|
||||||
|
*
|
||||||
|
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||||
|
* to wait for data to become available from the queue, should data not be
|
||||||
|
* available immediately. The actual amount of time this equates to is defined
|
||||||
|
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||||
|
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
|
||||||
|
* crQUEUE_SEND example).
|
||||||
|
*
|
||||||
|
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||||
|
* data was successfully retrieved from the queue, otherwise it will be set to
|
||||||
|
* an error code as defined within ProjDefs.h.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // A co-routine receives the number of an LED to flash from a queue. It
|
||||||
|
* // blocks on the queue until the number is received.
|
||||||
|
* static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static BaseType_t xResult;
|
||||||
|
* static UBaseType_t uxLEDToFlash;
|
||||||
|
*
|
||||||
|
* // All co-routines must start with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Wait for data to become available on the queue.
|
||||||
|
* crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // We received the LED to flash - flash it!
|
||||||
|
* vParTestToggleLED( uxLEDToFlash );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
|
||||||
|
{ \
|
||||||
|
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \
|
||||||
|
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE0( ( xHandle ) ); \
|
||||||
|
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \
|
||||||
|
} \
|
||||||
|
if( *( pxResult ) == errQUEUE_YIELD ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE1( ( xHandle ) ); \
|
||||||
|
*( pxResult ) = pdPASS; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* crQUEUE_SEND_FROM_ISR(
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvItemToQueue,
|
||||||
|
* BaseType_t xCoRoutinePreviouslyWoken
|
||||||
|
* )
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||||
|
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||||
|
* functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||||
|
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||||
|
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||||
|
* ISR.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
|
||||||
|
* that is being used from within a co-routine.
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||||
|
*
|
||||||
|
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
||||||
|
* queue. The size of the items the queue will hold was defined when the
|
||||||
|
* queue was created, so this many bytes will be copied from pvItemToQueue
|
||||||
|
* into the queue storage area.
|
||||||
|
*
|
||||||
|
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
|
||||||
|
* the same queue multiple times from a single interrupt. The first call
|
||||||
|
* should always pass in pdFALSE. Subsequent calls should pass in
|
||||||
|
* the value returned from the previous call.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
|
||||||
|
* used by the ISR to determine if a context switch may be required following
|
||||||
|
* the ISR.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // A co-routine that blocks on a queue waiting for characters to be received.
|
||||||
|
* static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* char cRxedChar;
|
||||||
|
* BaseType_t xResult;
|
||||||
|
*
|
||||||
|
* // All co-routines must start with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Wait for data to become available on the queue. This assumes the
|
||||||
|
* // queue xCommsRxQueue has already been created!
|
||||||
|
* crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* // Was a character received?
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // Process the character here.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // All co-routines must end with a call to crEND().
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // An ISR that uses a queue to send characters received on a serial port to
|
||||||
|
* // a co-routine.
|
||||||
|
* void vUART_ISR( void )
|
||||||
|
* {
|
||||||
|
* char cRxedChar;
|
||||||
|
* BaseType_t xCRWokenByPost = pdFALSE;
|
||||||
|
*
|
||||||
|
* // We loop around reading characters until there are none left in the UART.
|
||||||
|
* while( UART_RX_REG_NOT_EMPTY() )
|
||||||
|
* {
|
||||||
|
* // Obtain the character from the UART.
|
||||||
|
* cRxedChar = UART_RX_REG;
|
||||||
|
*
|
||||||
|
* // Post the character onto a queue. xCRWokenByPost will be pdFALSE
|
||||||
|
* // the first time around the loop. If the post causes a co-routine
|
||||||
|
* // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
|
||||||
|
* // In this manner we can ensure that if more than one co-routine is
|
||||||
|
* // blocked on the queue only one is woken by this ISR no matter how
|
||||||
|
* // many characters are posted to the queue.
|
||||||
|
* xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \
|
||||||
|
xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* <pre>
|
||||||
|
* crQUEUE_SEND_FROM_ISR(
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvBuffer,
|
||||||
|
* BaseType_t * pxCoRoutineWoken
|
||||||
|
* )
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||||
|
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||||
|
* functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||||
|
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||||
|
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||||
|
* ISR.
|
||||||
|
*
|
||||||
|
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
|
||||||
|
* from a queue that is being used from within a co-routine (a co-routine
|
||||||
|
* posted to the queue).
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||||
|
*
|
||||||
|
* @param pvBuffer A pointer to a buffer into which the received item will be
|
||||||
|
* placed. The size of the items the queue will hold was defined when the
|
||||||
|
* queue was created, so this many bytes will be copied from the queue into
|
||||||
|
* pvBuffer.
|
||||||
|
*
|
||||||
|
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
|
||||||
|
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
|
||||||
|
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
|
||||||
|
* *pxCoRoutineWoken will remain unchanged.
|
||||||
|
*
|
||||||
|
* @return pdTRUE an item was successfully received from the queue, otherwise
|
||||||
|
* pdFALSE.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // A co-routine that posts a character to a queue then blocks for a fixed
|
||||||
|
* // period. The character is incremented each time.
|
||||||
|
* static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // cChar holds its value while this co-routine is blocked and must therefore
|
||||||
|
* // be declared static.
|
||||||
|
* static char cCharToTx = 'a';
|
||||||
|
* BaseType_t xResult;
|
||||||
|
*
|
||||||
|
* // All co-routines must start with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Send the next character to the queue.
|
||||||
|
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // The character was successfully posted to the queue.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Could not post the character to the queue.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Enable the UART Tx interrupt to cause an interrupt in this
|
||||||
|
* // hypothetical UART. The interrupt will obtain the character
|
||||||
|
* // from the queue and send it.
|
||||||
|
* ENABLE_RX_INTERRUPT();
|
||||||
|
*
|
||||||
|
* // Increment to the next character then block for a fixed period.
|
||||||
|
* // cCharToTx will maintain its value across the delay as it is
|
||||||
|
* // declared static.
|
||||||
|
* cCharToTx++;
|
||||||
|
* if( cCharToTx > 'x' )
|
||||||
|
* {
|
||||||
|
* cCharToTx = 'a';
|
||||||
|
* }
|
||||||
|
* crDELAY( 100 );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // All co-routines must end with a call to crEND().
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // An ISR that uses a queue to receive characters to send on a UART.
|
||||||
|
* void vUART_ISR( void )
|
||||||
|
* {
|
||||||
|
* char cCharToTx;
|
||||||
|
* BaseType_t xCRWokenByPost = pdFALSE;
|
||||||
|
*
|
||||||
|
* while( UART_TX_REG_EMPTY() )
|
||||||
|
* {
|
||||||
|
* // Are there any characters in the queue waiting to be sent?
|
||||||
|
* // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
|
||||||
|
* // is woken by the post - ensuring that only a single co-routine is
|
||||||
|
* // woken no matter how many times we go around this loop.
|
||||||
|
* if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
|
||||||
|
* {
|
||||||
|
* SEND_CHARACTER( cCharToTx );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \
|
||||||
|
xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is intended for internal use by the co-routine macros only.
|
||||||
|
* The macro nature of the co-routine implementation requires that the
|
||||||
|
* prototype appears here. The function should not be used by application
|
||||||
|
* writers.
|
||||||
|
*
|
||||||
|
* Removes the current co-routine from its ready list and places it in the
|
||||||
|
* appropriate delayed list.
|
||||||
|
*/
|
||||||
|
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
|
||||||
|
List_t * pxEventList );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is intended for internal use by the queue implementation only.
|
||||||
|
* The function should not be used by application writers.
|
||||||
|
*
|
||||||
|
* Removes the highest priority co-routine from the event list and places it in
|
||||||
|
* the pending ready list.
|
||||||
|
*/
|
||||||
|
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* CO_ROUTINE_H */
|
||||||
@@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEPRECATED_DEFINITIONS_H
|
||||||
|
#define DEPRECATED_DEFINITIONS_H
|
||||||
|
|
||||||
|
|
||||||
|
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||||
|
* pre-processor definition was used to ensure the pre-processor found the correct
|
||||||
|
* portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||||
|
* of setting the compiler's include path such that it found the correct
|
||||||
|
* portmacro.h file - removing the need for the constant and allowing the
|
||||||
|
* portmacro.h file to be located anywhere in relation to the port being used. The
|
||||||
|
* definitions below remain in the code for backward compatibility only. New
|
||||||
|
* projects should not use them. */
|
||||||
|
|
||||||
|
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
|
||||||
|
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
|
||||||
|
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_MEGA_AVR
|
||||||
|
#include "../portable/GCC/ATMega323/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_MEGA_AVR
|
||||||
|
#include "../portable/IAR/ATMega323/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_PIC24_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_DSPIC_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_PIC18F_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_PIC32MX_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _FEDPICC
|
||||||
|
#include "libFreeRTOS/Include/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SDCC_CYGNAL
|
||||||
|
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARM7
|
||||||
|
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARM7_ECLIPSE
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ROWLEY_LPC23xx
|
||||||
|
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_MSP430
|
||||||
|
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_MSP430
|
||||||
|
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ROWLEY_MSP430
|
||||||
|
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARM7_LPC21xx_KEIL_RVDS
|
||||||
|
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAM7_GCC
|
||||||
|
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAM7_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAM9XE_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LPC2000_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR71X_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR75X_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR75X_GCC
|
||||||
|
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR91X_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_H8S
|
||||||
|
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_AT91FR40008
|
||||||
|
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RVDS_ARMCM3_LM3S102
|
||||||
|
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARMCM3_LM3S102
|
||||||
|
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARMCM3
|
||||||
|
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_ARM_CM3
|
||||||
|
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_ARMCM3_LM
|
||||||
|
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HCS12_CODE_WARRIOR
|
||||||
|
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MICROBLAZE_GCC
|
||||||
|
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TERN_EE
|
||||||
|
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_HCS12
|
||||||
|
#include "../../Source/portable/GCC/HCS12/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_MCF5235
|
||||||
|
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COLDFIRE_V2_GCC
|
||||||
|
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COLDFIRE_V2_CODEWARRIOR
|
||||||
|
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_PPC405
|
||||||
|
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_PPC440
|
||||||
|
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _16FX_SOFTUNE
|
||||||
|
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BCC_INDUSTRIAL_PC_PORT
|
||||||
|
|
||||||
|
/* A short file name has to be used in place of the normal
|
||||||
|
* FreeRTOSConfig.h when using the Borland compiler. */
|
||||||
|
#include "frconfig.h"
|
||||||
|
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BCC_FLASH_LITE_186_PORT
|
||||||
|
|
||||||
|
/* A short file name has to be used in place of the normal
|
||||||
|
* FreeRTOSConfig.h when using the Borland compiler. */
|
||||||
|
#include "frconfig.h"
|
||||||
|
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#ifdef __AVR32_AVR32A__
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ICCAVR32__
|
||||||
|
#ifdef __CORE__
|
||||||
|
#if __CORE__ == __AVR32A__
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __91467D
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __96340
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Fx3__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Jx3__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Jx3_L__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Jx2__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Hx2__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_78K0R_Kx3__
|
||||||
|
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_78K0R_Kx3L__
|
||||||
|
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEPRECATED_DEFINITIONS_H */
|
||||||
@@ -0,0 +1,775 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_GROUPS_H
|
||||||
|
#define EVENT_GROUPS_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event group is a collection of bits to which an application can assign a
|
||||||
|
* meaning. For example, an application may create an event group to convey
|
||||||
|
* the status of various CAN bus related events in which bit 0 might mean "A CAN
|
||||||
|
* message has been received and is ready for processing", bit 1 might mean "The
|
||||||
|
* application has queued a message that is ready for sending onto the CAN
|
||||||
|
* network", and bit 2 might mean "It is time to send a SYNC message onto the
|
||||||
|
* CAN network" etc. A task can then test the bit values to see which events
|
||||||
|
* are active, and optionally enter the Blocked state to wait for a specified
|
||||||
|
* bit or a group of specified bits to be active. To continue the CAN bus
|
||||||
|
* example, a CAN controlling task can enter the Blocked state (and therefore
|
||||||
|
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
|
||||||
|
* active, at which time the bit that was actually active would inform the task
|
||||||
|
* which action it had to take (process a received message, send a message, or
|
||||||
|
* send a SYNC).
|
||||||
|
*
|
||||||
|
* The event groups implementation contains intelligence to avoid race
|
||||||
|
* conditions that would otherwise occur were an application to use a simple
|
||||||
|
* variable for the same purpose. This is particularly important with respect
|
||||||
|
* to when a bit within an event group is to be cleared, and when bits have to
|
||||||
|
* be set and then tested atomically - as is the case where event groups are
|
||||||
|
* used to create a synchronisation point between multiple tasks (a
|
||||||
|
* 'rendezvous').
|
||||||
|
*
|
||||||
|
* \defgroup EventGroup
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
*
|
||||||
|
* Type by which event groups are referenced. For example, a call to
|
||||||
|
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
|
||||||
|
* be used as a parameter to other event group functions.
|
||||||
|
*
|
||||||
|
* \defgroup EventGroupHandle_t EventGroupHandle_t
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
struct EventGroupDef_t;
|
||||||
|
typedef struct EventGroupDef_t * EventGroupHandle_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The type that holds event bits always matches TickType_t - therefore the
|
||||||
|
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
|
||||||
|
* 32 bits if set to 0.
|
||||||
|
*
|
||||||
|
* \defgroup EventBits_t EventBits_t
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
typedef TickType_t EventBits_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventGroupHandle_t xEventGroupCreate( void );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Create a new event group.
|
||||||
|
*
|
||||||
|
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||||
|
* block of memory, in which the event group's structure is stored. If an event
|
||||||
|
* groups is created using xEventGropuCreate() then the required memory is
|
||||||
|
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||||
|
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
|
||||||
|
* using xEventGropuCreateStatic() then the application writer must instead
|
||||||
|
* provide the memory that will get used by the event group.
|
||||||
|
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||||
|
* without using any dynamic memory allocation.
|
||||||
|
*
|
||||||
|
* Although event groups are not related to ticks, for internal implementation
|
||||||
|
* reasons the number of bits available for use in an event group is dependent
|
||||||
|
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
|
||||||
|
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
|
||||||
|
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
|
||||||
|
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
|
||||||
|
* event bits within an event group.
|
||||||
|
*
|
||||||
|
* @return If the event group was created then a handle to the event group is
|
||||||
|
* returned. If there was insufficient FreeRTOS heap available to create the
|
||||||
|
* event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Declare a variable to hold the created event group.
|
||||||
|
* EventGroupHandle_t xCreatedEventGroup;
|
||||||
|
*
|
||||||
|
* // Attempt to create the event group.
|
||||||
|
* xCreatedEventGroup = xEventGroupCreate();
|
||||||
|
*
|
||||||
|
* // Was the event group created successfully?
|
||||||
|
* if( xCreatedEventGroup == NULL )
|
||||||
|
* {
|
||||||
|
* // The event group was not created because there was insufficient
|
||||||
|
* // FreeRTOS heap available.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // The event group was created.
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupCreate xEventGroupCreate
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Create a new event group.
|
||||||
|
*
|
||||||
|
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||||
|
* block of memory, in which the event group's structure is stored. If an event
|
||||||
|
* groups is created using xEventGropuCreate() then the required memory is
|
||||||
|
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||||
|
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
|
||||||
|
* using xEventGropuCreateStatic() then the application writer must instead
|
||||||
|
* provide the memory that will get used by the event group.
|
||||||
|
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||||
|
* without using any dynamic memory allocation.
|
||||||
|
*
|
||||||
|
* Although event groups are not related to ticks, for internal implementation
|
||||||
|
* reasons the number of bits available for use in an event group is dependent
|
||||||
|
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
|
||||||
|
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
|
||||||
|
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
|
||||||
|
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
|
||||||
|
* event bits within an event group.
|
||||||
|
*
|
||||||
|
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
|
||||||
|
* StaticEventGroup_t, which will be then be used to hold the event group's data
|
||||||
|
* structures, removing the need for the memory to be allocated dynamically.
|
||||||
|
*
|
||||||
|
* @return If the event group was created then a handle to the event group is
|
||||||
|
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // StaticEventGroup_t is a publicly accessible structure that has the same
|
||||||
|
* // size and alignment requirements as the real event group structure. It is
|
||||||
|
* // provided as a mechanism for applications to know the size of the event
|
||||||
|
* // group (which is dependent on the architecture and configuration file
|
||||||
|
* // settings) without breaking the strict data hiding policy by exposing the
|
||||||
|
* // real event group internals. This StaticEventGroup_t variable is passed
|
||||||
|
* // into the xSemaphoreCreateEventGroupStatic() function and is used to store
|
||||||
|
* // the event group's data structures
|
||||||
|
* StaticEventGroup_t xEventGroupBuffer;
|
||||||
|
*
|
||||||
|
* // Create the event group without dynamically allocating any memory.
|
||||||
|
* xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
* const EventBits_t uxBitsToWaitFor,
|
||||||
|
* const BaseType_t xClearOnExit,
|
||||||
|
* const BaseType_t xWaitForAllBits,
|
||||||
|
* const TickType_t xTicksToWait );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* [Potentially] block to wait for one or more bits to be set within a
|
||||||
|
* previously created event group.
|
||||||
|
*
|
||||||
|
* This function cannot be called from an interrupt.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are being tested. The
|
||||||
|
* event group must have previously been created using a call to
|
||||||
|
* xEventGroupCreate().
|
||||||
|
*
|
||||||
|
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||||
|
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x07. Etc.
|
||||||
|
*
|
||||||
|
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
|
||||||
|
* uxBitsToWaitFor that are set within the event group will be cleared before
|
||||||
|
* xEventGroupWaitBits() returns if the wait condition was met (if the function
|
||||||
|
* returns for a reason other than a timeout). If xClearOnExit is set to
|
||||||
|
* pdFALSE then the bits set in the event group are not altered when the call to
|
||||||
|
* xEventGroupWaitBits() returns.
|
||||||
|
*
|
||||||
|
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
|
||||||
|
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
|
||||||
|
* are set or the specified block time expires. If xWaitForAllBits is set to
|
||||||
|
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
|
||||||
|
* in uxBitsToWaitFor is set or the specified block time expires. The block
|
||||||
|
* time is specified by the xTicksToWait parameter.
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||||
|
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
|
||||||
|
* uxBitsToWaitFor to become set.
|
||||||
|
*
|
||||||
|
* @return The value of the event group at the time either the bits being waited
|
||||||
|
* for became set, or the block time expired. Test the return value to know
|
||||||
|
* which bits were set. If xEventGroupWaitBits() returned because its timeout
|
||||||
|
* expired then not all the bits being waited for will be set. If
|
||||||
|
* xEventGroupWaitBits() returned because the bits it was waiting for were set
|
||||||
|
* then the returned value is the event group value before any bits were
|
||||||
|
* automatically cleared in the case that xClearOnExit parameter was set to
|
||||||
|
* pdTRUE.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
#define BIT_0 ( 1 << 0 )
|
||||||
|
#define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxBits;
|
||||||
|
* const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||||
|
*
|
||||||
|
* // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
|
||||||
|
* // the event group. Clear the bits before exiting.
|
||||||
|
* uxBits = xEventGroupWaitBits(
|
||||||
|
* xEventGroup, // The event group being tested.
|
||||||
|
* BIT_0 | BIT_4, // The bits within the event group to wait for.
|
||||||
|
* pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
|
||||||
|
* pdFALSE, // Don't wait for both bits, either bit will do.
|
||||||
|
* xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
|
||||||
|
*
|
||||||
|
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because both bits were set.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because just BIT_0 was set.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because just BIT_4 was set.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because xTicksToWait ticks passed
|
||||||
|
* // without either BIT_0 or BIT_4 becoming set.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Clear bits within an event group. This function cannot be called from an
|
||||||
|
* interrupt.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||||
|
*
|
||||||
|
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
|
||||||
|
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
|
||||||
|
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
|
||||||
|
*
|
||||||
|
* @return The value of the event group before the specified bits were cleared.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
#define BIT_0 ( 1 << 0 )
|
||||||
|
#define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxBits;
|
||||||
|
*
|
||||||
|
* // Clear bit 0 and bit 4 in xEventGroup.
|
||||||
|
* uxBits = xEventGroupClearBits(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 );// The bits being cleared.
|
||||||
|
*
|
||||||
|
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||||
|
* {
|
||||||
|
* // Both bit 0 and bit 4 were set before xEventGroupClearBits() was
|
||||||
|
* // called. Both will now be clear (not set).
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 0 was set before xEventGroupClearBits() was called. It will
|
||||||
|
* // now be clear.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 4 was set before xEventGroupClearBits() was called. It will
|
||||||
|
* // now be clear.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Neither bit 0 nor bit 4 were set in the first place.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupClearBits xEventGroupClearBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* A version of xEventGroupClearBits() that can be called from an interrupt.
|
||||||
|
*
|
||||||
|
* Setting bits in an event group is not a deterministic operation because there
|
||||||
|
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||||
|
* set. FreeRTOS does not allow nondeterministic operations to be performed
|
||||||
|
* while interrupts are disabled, so protects event groups that are accessed
|
||||||
|
* from tasks by suspending the scheduler rather than disabling interrupts. As
|
||||||
|
* a result event groups cannot be accessed directly from an interrupt service
|
||||||
|
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
|
||||||
|
* timer task to have the clear operation performed in the context of the timer
|
||||||
|
* task.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||||
|
*
|
||||||
|
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
|
||||||
|
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
|
||||||
|
* and bit 0 set uxBitsToClear to 0x09.
|
||||||
|
*
|
||||||
|
* @return If the request to execute the function was posted successfully then
|
||||||
|
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||||
|
* if the timer service queue was full.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
#define BIT_0 ( 1 << 0 )
|
||||||
|
#define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* // An event group which it is assumed has already been created by a call to
|
||||||
|
* // xEventGroupCreate().
|
||||||
|
* EventGroupHandle_t xEventGroup;
|
||||||
|
*
|
||||||
|
* void anInterruptHandler( void )
|
||||||
|
* {
|
||||||
|
* // Clear bit 0 and bit 4 in xEventGroup.
|
||||||
|
* xResult = xEventGroupClearBitsFromISR(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 ); // The bits being set.
|
||||||
|
*
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // The message was posted successfully.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
#else
|
||||||
|
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \
|
||||||
|
xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Set bits within an event group.
|
||||||
|
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
|
||||||
|
* is a version that can be called from an interrupt.
|
||||||
|
*
|
||||||
|
* Setting bits in an event group will automatically unblock tasks that are
|
||||||
|
* blocked waiting for the bits.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be set.
|
||||||
|
*
|
||||||
|
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||||
|
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||||
|
* and bit 0 set uxBitsToSet to 0x09.
|
||||||
|
*
|
||||||
|
* @return The value of the event group at the time the call to
|
||||||
|
* xEventGroupSetBits() returns. There are two reasons why the returned value
|
||||||
|
* might have the bits specified by the uxBitsToSet parameter cleared. First,
|
||||||
|
* if setting a bit results in a task that was waiting for the bit leaving the
|
||||||
|
* blocked state then it is possible the bit will be cleared automatically
|
||||||
|
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
|
||||||
|
* unblocked (or otherwise Ready state) task that has a priority above that of
|
||||||
|
* the task that called xEventGroupSetBits() will execute and may change the
|
||||||
|
* event group value before the call to xEventGroupSetBits() returns.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
#define BIT_0 ( 1 << 0 )
|
||||||
|
#define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxBits;
|
||||||
|
*
|
||||||
|
* // Set bit 0 and bit 4 in xEventGroup.
|
||||||
|
* uxBits = xEventGroupSetBits(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 );// The bits being set.
|
||||||
|
*
|
||||||
|
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||||
|
* {
|
||||||
|
* // Both bit 0 and bit 4 remained set when the function returned.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 0 remained set when the function returned, but bit 4 was
|
||||||
|
* // cleared. It might be that bit 4 was cleared automatically as a
|
||||||
|
* // task that was waiting for bit 4 was removed from the Blocked
|
||||||
|
* // state.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 4 remained set when the function returned, but bit 0 was
|
||||||
|
* // cleared. It might be that bit 0 was cleared automatically as a
|
||||||
|
* // task that was waiting for bit 0 was removed from the Blocked
|
||||||
|
* // state.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Neither bit 0 nor bit 4 remained set. It might be that a task
|
||||||
|
* // was waiting for both of the bits to be set, and the bits were
|
||||||
|
* // cleared as the task left the Blocked state.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupSetBits xEventGroupSetBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* A version of xEventGroupSetBits() that can be called from an interrupt.
|
||||||
|
*
|
||||||
|
* Setting bits in an event group is not a deterministic operation because there
|
||||||
|
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||||
|
* set. FreeRTOS does not allow nondeterministic operations to be performed in
|
||||||
|
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
|
||||||
|
* sends a message to the timer task to have the set operation performed in the
|
||||||
|
* context of the timer task - where a scheduler lock is used in place of a
|
||||||
|
* critical section.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be set.
|
||||||
|
*
|
||||||
|
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||||
|
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||||
|
* and bit 0 set uxBitsToSet to 0x09.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
|
||||||
|
* will result in a message being sent to the timer daemon task. If the
|
||||||
|
* priority of the timer daemon task is higher than the priority of the
|
||||||
|
* currently running task (the task the interrupt interrupted) then
|
||||||
|
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
|
||||||
|
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
|
||||||
|
* requested before the interrupt exits. For that reason
|
||||||
|
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
|
||||||
|
* example code below.
|
||||||
|
*
|
||||||
|
* @return If the request to execute the function was posted successfully then
|
||||||
|
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||||
|
* if the timer service queue was full.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
#define BIT_0 ( 1 << 0 )
|
||||||
|
#define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* // An event group which it is assumed has already been created by a call to
|
||||||
|
* // xEventGroupCreate().
|
||||||
|
* EventGroupHandle_t xEventGroup;
|
||||||
|
*
|
||||||
|
* void anInterruptHandler( void )
|
||||||
|
* {
|
||||||
|
* BaseType_t xHigherPriorityTaskWoken, xResult;
|
||||||
|
*
|
||||||
|
* // xHigherPriorityTaskWoken must be initialised to pdFALSE.
|
||||||
|
* xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
*
|
||||||
|
* // Set bit 0 and bit 4 in xEventGroup.
|
||||||
|
* xResult = xEventGroupSetBitsFromISR(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 // The bits being set.
|
||||||
|
* &xHigherPriorityTaskWoken );
|
||||||
|
*
|
||||||
|
* // Was the message posted successfully?
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
|
||||||
|
* // switch should be requested. The macro used is port specific and
|
||||||
|
* // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
|
||||||
|
* // refer to the documentation page for the port being used.
|
||||||
|
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
#else
|
||||||
|
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \
|
||||||
|
xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
* const EventBits_t uxBitsToSet,
|
||||||
|
* const EventBits_t uxBitsToWaitFor,
|
||||||
|
* TickType_t xTicksToWait );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Atomically set bits within an event group, then wait for a combination of
|
||||||
|
* bits to be set within the same event group. This functionality is typically
|
||||||
|
* used to synchronise multiple tasks, where each task has to wait for the other
|
||||||
|
* tasks to reach a synchronisation point before proceeding.
|
||||||
|
*
|
||||||
|
* This function cannot be used from an interrupt.
|
||||||
|
*
|
||||||
|
* The function will return before its block time expires if the bits specified
|
||||||
|
* by the uxBitsToWait parameter are set, or become set within that time. In
|
||||||
|
* this case all the bits specified by uxBitsToWait will be automatically
|
||||||
|
* cleared before the function returns.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are being tested. The
|
||||||
|
* event group must have previously been created using a call to
|
||||||
|
* xEventGroupCreate().
|
||||||
|
*
|
||||||
|
* @param uxBitsToSet The bits to set in the event group before determining
|
||||||
|
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
|
||||||
|
* parameter are set.
|
||||||
|
*
|
||||||
|
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||||
|
* inside the event group. For example, to wait for bit 0 and bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x07. Etc.
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||||
|
* for all of the bits specified by uxBitsToWaitFor to become set.
|
||||||
|
*
|
||||||
|
* @return The value of the event group at the time either the bits being waited
|
||||||
|
* for became set, or the block time expired. Test the return value to know
|
||||||
|
* which bits were set. If xEventGroupSync() returned because its timeout
|
||||||
|
* expired then not all the bits being waited for will be set. If
|
||||||
|
* xEventGroupSync() returned because all the bits it was waiting for were
|
||||||
|
* set then the returned value is the event group value before any bits were
|
||||||
|
* automatically cleared.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <pre>
|
||||||
|
* // Bits used by the three tasks.
|
||||||
|
#define TASK_0_BIT ( 1 << 0 )
|
||||||
|
#define TASK_1_BIT ( 1 << 1 )
|
||||||
|
#define TASK_2_BIT ( 1 << 2 )
|
||||||
|
*
|
||||||
|
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
|
||||||
|
*
|
||||||
|
* // Use an event group to synchronise three tasks. It is assumed this event
|
||||||
|
* // group has already been created elsewhere.
|
||||||
|
* EventGroupHandle_t xEventBits;
|
||||||
|
*
|
||||||
|
* void vTask0( void *pvParameters )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxReturn;
|
||||||
|
* TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Perform task functionality here.
|
||||||
|
*
|
||||||
|
* // Set bit 0 in the event flag to note this task has reached the
|
||||||
|
* // sync point. The other two tasks will set the other two bits defined
|
||||||
|
* // by ALL_SYNC_BITS. All three tasks have reached the synchronisation
|
||||||
|
* // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
|
||||||
|
* // for this to happen.
|
||||||
|
* uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
|
||||||
|
*
|
||||||
|
* if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
|
||||||
|
* {
|
||||||
|
* // All three tasks reached the synchronisation point before the call
|
||||||
|
* // to xEventGroupSync() timed out.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void vTask1( void *pvParameters )
|
||||||
|
* {
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Perform task functionality here.
|
||||||
|
*
|
||||||
|
* // Set bit 1 in the event flag to note this task has reached the
|
||||||
|
* // synchronisation point. The other two tasks will set the other two
|
||||||
|
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||||
|
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||||
|
* // indefinitely for this to happen.
|
||||||
|
* xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
*
|
||||||
|
* // xEventGroupSync() was called with an indefinite block time, so
|
||||||
|
* // this task will only reach here if the synchronisation was made by all
|
||||||
|
* // three tasks, so there is no need to test the return value.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void vTask2( void *pvParameters )
|
||||||
|
* {
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Perform task functionality here.
|
||||||
|
*
|
||||||
|
* // Set bit 2 in the event flag to note this task has reached the
|
||||||
|
* // synchronisation point. The other two tasks will set the other two
|
||||||
|
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||||
|
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||||
|
* // indefinitely for this to happen.
|
||||||
|
* xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
*
|
||||||
|
* // xEventGroupSync() was called with an indefinite block time, so
|
||||||
|
* // this task will only reach here if the synchronisation was made by all
|
||||||
|
* // three tasks, so there is no need to test the return value.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xEventGroupSync xEventGroupSync
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Returns the current value of the bits in an event group. This function
|
||||||
|
* cannot be used from an interrupt.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group being queried.
|
||||||
|
*
|
||||||
|
* @return The event group bits at the time xEventGroupGetBits() was called.
|
||||||
|
*
|
||||||
|
* \defgroup xEventGroupGetBits xEventGroupGetBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* A version of xEventGroupGetBits() that can be called from an ISR.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group being queried.
|
||||||
|
*
|
||||||
|
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
|
||||||
|
*
|
||||||
|
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* <pre>
|
||||||
|
* void xEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Delete an event group that was previously created by a call to
|
||||||
|
* xEventGroupCreate(). Tasks that are blocked on the event group will be
|
||||||
|
* unblocked and obtain 0 as the event group's value.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group being deleted.
|
||||||
|
*/
|
||||||
|
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* For internal use only. */
|
||||||
|
void vEventGroupSetBitsCallback( void * pvEventGroup,
|
||||||
|
const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
|
||||||
|
void vEventGroupClearBitsCallback( void * pvEventGroup,
|
||||||
|
const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
void vEventGroupSetNumber( void * xEventGroup,
|
||||||
|
UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* EVENT_GROUPS_H */
|
||||||
@@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the list implementation used by the scheduler. While it is tailored
|
||||||
|
* heavily for the schedulers needs, it is also available for use by
|
||||||
|
* application code.
|
||||||
|
*
|
||||||
|
* list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
|
||||||
|
* numeric value (xItemValue). Most of the time the lists are sorted in
|
||||||
|
* descending item value order.
|
||||||
|
*
|
||||||
|
* Lists are created already containing one list item. The value of this
|
||||||
|
* item is the maximum possible that can be stored, it is therefore always at
|
||||||
|
* the end of the list and acts as a marker. The list member pxHead always
|
||||||
|
* points to this marker - even though it is at the tail of the list. This
|
||||||
|
* is because the tail contains a wrap back pointer to the true head of
|
||||||
|
* the list.
|
||||||
|
*
|
||||||
|
* In addition to it's value, each list item contains a pointer to the next
|
||||||
|
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
|
||||||
|
* and a pointer to back to the object that contains it. These later two
|
||||||
|
* pointers are included for efficiency of list manipulation. There is
|
||||||
|
* effectively a two way link between the object containing the list item and
|
||||||
|
* the list item itself.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \page ListIntroduction List Implementation
|
||||||
|
* \ingroup FreeRTOSIntro
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "FreeRTOS.h must be included before list.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The list structure members are modified from within interrupts, and therefore
|
||||||
|
* by rights should be declared volatile. However, they are only modified in a
|
||||||
|
* functionally atomic way (within critical sections of with the scheduler
|
||||||
|
* suspended) and are either passed by reference into a function or indexed via
|
||||||
|
* a volatile variable. Therefore, in all use cases tested so far, the volatile
|
||||||
|
* qualifier can be omitted in order to provide a moderate performance
|
||||||
|
* improvement without adversely affecting functional behaviour. The assembly
|
||||||
|
* instructions generated by the IAR, ARM and GCC compilers when the respective
|
||||||
|
* compiler's options were set for maximum optimisation has been inspected and
|
||||||
|
* deemed to be as intended. That said, as compiler technology advances, and
|
||||||
|
* especially if aggressive cross module optimisation is used (a use case that
|
||||||
|
* has not been exercised to any great extend) then it is feasible that the
|
||||||
|
* volatile qualifier will be needed for correct optimisation. It is expected
|
||||||
|
* that a compiler removing essential code because, without the volatile
|
||||||
|
* qualifier on the list structure members and with aggressive cross module
|
||||||
|
* optimisation, the compiler deemed the code unnecessary will result in
|
||||||
|
* complete and obvious failure of the scheduler. If this is ever experienced
|
||||||
|
* then the volatile qualifier can be inserted in the relevant places within the
|
||||||
|
* list structures by simply defining configLIST_VOLATILE to volatile in
|
||||||
|
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
|
||||||
|
* If configLIST_VOLATILE is not defined then the preprocessor directives below
|
||||||
|
* will simply #define configLIST_VOLATILE away completely.
|
||||||
|
*
|
||||||
|
* To use volatile list structure members then add the following line to
|
||||||
|
* FreeRTOSConfig.h (without the quotes):
|
||||||
|
* "#define configLIST_VOLATILE volatile"
|
||||||
|
*/
|
||||||
|
#ifndef configLIST_VOLATILE
|
||||||
|
#define configLIST_VOLATILE
|
||||||
|
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/* Macros that can be used to place known values within the list structures,
|
||||||
|
* then check that the known values do not get corrupted during the execution of
|
||||||
|
* the application. These may catch the list data structures being overwritten in
|
||||||
|
* memory. They will not catch data errors caused by incorrect configuration or
|
||||||
|
* use of FreeRTOS.*/
|
||||||
|
#if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
|
||||||
|
/* Define the macros to do nothing. */
|
||||||
|
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||||
|
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
|
||||||
|
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
|
||||||
|
#define listTEST_LIST_INTEGRITY( pxList )
|
||||||
|
#else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */
|
||||||
|
/* Define macros that add new members into the list structures. */
|
||||||
|
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
|
||||||
|
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
|
||||||
|
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
|
||||||
|
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
|
||||||
|
|
||||||
|
/* Define macros that set the new structure members to known values. */
|
||||||
|
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
|
||||||
|
/* Define macros that will assert if one of the structure members does not
|
||||||
|
* contain its expected value. */
|
||||||
|
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||||
|
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||||
|
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of the only type of object that a list can contain.
|
||||||
|
*/
|
||||||
|
struct xLIST;
|
||||||
|
struct xLIST_ITEM
|
||||||
|
{
|
||||||
|
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
|
||||||
|
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
|
||||||
|
struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */
|
||||||
|
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
};
|
||||||
|
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
|
||||||
|
|
||||||
|
struct xMINI_LIST_ITEM
|
||||||
|
{
|
||||||
|
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
configLIST_VOLATILE TickType_t xItemValue;
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
|
||||||
|
};
|
||||||
|
typedef struct xMINI_LIST_ITEM MiniListItem_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of the type of queue used by the scheduler.
|
||||||
|
*/
|
||||||
|
typedef struct xLIST
|
||||||
|
{
|
||||||
|
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
volatile UBaseType_t uxNumberOfItems;
|
||||||
|
ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
|
||||||
|
MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
|
||||||
|
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
} List_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to set the owner of a list item. The owner of a list item
|
||||||
|
* is the object (usually a TCB) that contains the list item.
|
||||||
|
*
|
||||||
|
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to get the owner of a list item. The owner of a list item
|
||||||
|
* is the object (usually a TCB) that contains the list item.
|
||||||
|
*
|
||||||
|
* \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to set the value of the list item. In most cases the value is
|
||||||
|
* used to sort the list in descending order.
|
||||||
|
*
|
||||||
|
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to retrieve the value of the list item. The value can
|
||||||
|
* represent anything - for example the priority of a task, or the time at
|
||||||
|
* which a task should be unblocked.
|
||||||
|
*
|
||||||
|
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to retrieve the value of the list item at the head of a given
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list item at the head of the list.
|
||||||
|
*
|
||||||
|
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next list item.
|
||||||
|
*
|
||||||
|
* \page listGET_NEXT listGET_NEXT
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list item that marks the end of the list
|
||||||
|
*
|
||||||
|
* \page listGET_END_MARKER listGET_END_MARKER
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to determine if a list contains any items. The macro will
|
||||||
|
* only have the value true if the list is empty.
|
||||||
|
*
|
||||||
|
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to return the number of items in the list.
|
||||||
|
*/
|
||||||
|
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access function to obtain the owner of the next entry in a list.
|
||||||
|
*
|
||||||
|
* The list member pxIndex is used to walk through a list. Calling
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
|
||||||
|
* and returns that entry's pxOwner parameter. Using multiple calls to this
|
||||||
|
* function it is therefore possible to move through every item contained in
|
||||||
|
* a list.
|
||||||
|
*
|
||||||
|
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||||
|
* the list item. In the scheduler this is normally a task control block.
|
||||||
|
* The pxOwner parameter effectively creates a two way link between the list
|
||||||
|
* item and its owner.
|
||||||
|
*
|
||||||
|
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
|
||||||
|
* @param pxList The list from which the next item owner is to be returned.
|
||||||
|
*
|
||||||
|
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
|
||||||
|
{ \
|
||||||
|
List_t * const pxConstList = ( pxList ); \
|
||||||
|
/* Increment the index to the next item and return the item, ensuring */ \
|
||||||
|
/* we don't return the marker used at the end of the list. */ \
|
||||||
|
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||||
|
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
|
||||||
|
{ \
|
||||||
|
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||||
|
} \
|
||||||
|
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access function to obtain the owner of the first entry in a list. Lists
|
||||||
|
* are normally sorted in ascending item value order.
|
||||||
|
*
|
||||||
|
* This function returns the pxOwner member of the first item in the list.
|
||||||
|
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||||
|
* the list item. In the scheduler this is normally a task control block.
|
||||||
|
* The pxOwner parameter effectively creates a two way link between the list
|
||||||
|
* item and its owner.
|
||||||
|
*
|
||||||
|
* @param pxList The list from which the owner of the head item is to be
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if a list item is within a list. The list item maintains a
|
||||||
|
* "container" pointer that points to the list it is in. All this macro does
|
||||||
|
* is check to see if the container and the list match.
|
||||||
|
*
|
||||||
|
* @param pxList The list we want to know if the list item is within.
|
||||||
|
* @param pxListItem The list item we want to know if is in the list.
|
||||||
|
* @return pdTRUE if the list item is in the list, otherwise pdFALSE.
|
||||||
|
*/
|
||||||
|
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list a list item is contained within (referenced from).
|
||||||
|
*
|
||||||
|
* @param pxListItem The list item being queried.
|
||||||
|
* @return A pointer to the List_t object that references the pxListItem
|
||||||
|
*/
|
||||||
|
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This provides a crude means of knowing if a list has been initialised, as
|
||||||
|
* pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called before a list is used! This initialises all the members
|
||||||
|
* of the list structure and inserts the xListEnd item into the list as a
|
||||||
|
* marker to the back of the list.
|
||||||
|
*
|
||||||
|
* @param pxList Pointer to the list being initialised.
|
||||||
|
*
|
||||||
|
* \page vListInitialise vListInitialise
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called before a list item is used. This sets the list container to
|
||||||
|
* null so the item does not think that it is already contained in a list.
|
||||||
|
*
|
||||||
|
* @param pxItem Pointer to the list item being initialised.
|
||||||
|
*
|
||||||
|
* \page vListInitialiseItem vListInitialiseItem
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a list item into a list. The item will be inserted into the list in
|
||||||
|
* a position determined by its item value (descending item value order).
|
||||||
|
*
|
||||||
|
* @param pxList The list into which the item is to be inserted.
|
||||||
|
*
|
||||||
|
* @param pxNewListItem The item that is to be placed in the list.
|
||||||
|
*
|
||||||
|
* \page vListInsert vListInsert
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInsert( List_t * const pxList,
|
||||||
|
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a list item into a list. The item will be inserted in a position
|
||||||
|
* such that it will be the last item within the list returned by multiple
|
||||||
|
* calls to listGET_OWNER_OF_NEXT_ENTRY.
|
||||||
|
*
|
||||||
|
* The list member pxIndex is used to walk through a list. Calling
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||||
|
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||||
|
* in the list position pointed to by pxIndex. This means that every other
|
||||||
|
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||||
|
* the pxIndex parameter again points to the item being inserted.
|
||||||
|
*
|
||||||
|
* @param pxList The list into which the item is to be inserted.
|
||||||
|
*
|
||||||
|
* @param pxNewListItem The list item to be inserted into the list.
|
||||||
|
*
|
||||||
|
* \page vListInsertEnd vListInsertEnd
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInsertEnd( List_t * const pxList,
|
||||||
|
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove an item from a list. The list item has a pointer to the list that
|
||||||
|
* it is in, so only the list item need be passed into the function.
|
||||||
|
*
|
||||||
|
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||||
|
* the list pointed to by it's pxContainer parameter.
|
||||||
|
*
|
||||||
|
* @return The number of items that remain in the list after the list item has
|
||||||
|
* been removed.
|
||||||
|
*
|
||||||
|
* \page uxListRemove uxListRemove
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* ifndef LIST_H */
|
||||||
@@ -0,0 +1,821 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message buffers build functionality on top of FreeRTOS stream buffers.
|
||||||
|
* Whereas stream buffers are used to send a continuous stream of data from one
|
||||||
|
* task or interrupt to another, message buffers are used to send variable
|
||||||
|
* length discrete messages from one task or interrupt to another. Their
|
||||||
|
* implementation is light weight, making them particularly suited for interrupt
|
||||||
|
* to task and core to core communication scenarios.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must place each call to a writing API function
|
||||||
|
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||||
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
|
* then the application writer must place each call to a reading API function
|
||||||
|
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||||
|
* timeout to 0.
|
||||||
|
*
|
||||||
|
* Message buffers hold variable length messages. To enable that, when a
|
||||||
|
* message is written to the message buffer an additional sizeof( size_t ) bytes
|
||||||
|
* are also written to store the message's length (that happens internally, with
|
||||||
|
* the API function). sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||||
|
* architecture, so writing a 10 byte message to a message buffer on a 32-bit
|
||||||
|
* architecture will actually reduce the available space in the message buffer
|
||||||
|
* by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
|
||||||
|
* of the message).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERTOS_MESSAGE_BUFFER_H
|
||||||
|
#define FREERTOS_MESSAGE_BUFFER_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h must appear in source files before include message_buffer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Message buffers are built onto of stream buffers. */
|
||||||
|
#include "stream_buffer.h"
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#if defined( __cplusplus )
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type by which message buffers are referenced. For example, a call to
|
||||||
|
* xMessageBufferCreate() returns an MessageBufferHandle_t variable that can
|
||||||
|
* then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
|
||||||
|
* etc.
|
||||||
|
*/
|
||||||
|
typedef void * MessageBufferHandle_t;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Creates a new message buffer using dynamically allocated memory. See
|
||||||
|
* xMessageBufferCreateStatic() for a version that uses statically allocated
|
||||||
|
* memory (memory that is allocated at compile time).
|
||||||
|
*
|
||||||
|
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
|
||||||
|
* FreeRTOSConfig.h for xMessageBufferCreate() to be available.
|
||||||
|
*
|
||||||
|
* @param xBufferSizeBytes The total number of bytes (not messages) the message
|
||||||
|
* buffer will be able to hold at any one time. When a message is written to
|
||||||
|
* the message buffer an additional sizeof( size_t ) bytes are also written to
|
||||||
|
* store the message's length. sizeof( size_t ) is typically 4 bytes on a
|
||||||
|
* 32-bit architecture, so on most 32-bit architectures a 10 byte message will
|
||||||
|
* take up 14 bytes of message buffer space.
|
||||||
|
*
|
||||||
|
* @return If NULL is returned, then the message buffer cannot be created
|
||||||
|
* because there is insufficient heap memory available for FreeRTOS to allocate
|
||||||
|
* the message buffer data structures and storage area. A non-NULL value being
|
||||||
|
* returned indicates that the message buffer has been created successfully -
|
||||||
|
* the returned value should be stored as the handle to the created message
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* void vAFunction( void )
|
||||||
|
* {
|
||||||
|
* MessageBufferHandle_t xMessageBuffer;
|
||||||
|
* const size_t xMessageBufferSizeBytes = 100;
|
||||||
|
*
|
||||||
|
* // Create a message buffer that can hold 100 bytes. The memory used to hold
|
||||||
|
* // both the message buffer structure and the messages themselves is allocated
|
||||||
|
* // dynamically. Each message added to the buffer consumes an additional 4
|
||||||
|
* // bytes which are used to hold the lengh of the message.
|
||||||
|
* xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
|
||||||
|
*
|
||||||
|
* if( xMessageBuffer == NULL )
|
||||||
|
* {
|
||||||
|
* // There was not enough heap memory space available to create the
|
||||||
|
* // message buffer.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // The message buffer was created successfully and can now be used.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xMessageBufferCreate xMessageBufferCreate
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferCreate( xBufferSizeBytes ) \
|
||||||
|
( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
|
||||||
|
* uint8_t *pucMessageBufferStorageArea,
|
||||||
|
* StaticMessageBuffer_t *pxStaticMessageBuffer );
|
||||||
|
* </pre>
|
||||||
|
* Creates a new message buffer using statically allocated memory. See
|
||||||
|
* xMessageBufferCreate() for a version that uses dynamically allocated memory.
|
||||||
|
*
|
||||||
|
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
|
||||||
|
* pucMessageBufferStorageArea parameter. When a message is written to the
|
||||||
|
* message buffer an additional sizeof( size_t ) bytes are also written to store
|
||||||
|
* the message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||||
|
* architecture, so on most 32-bit architecture a 10 byte message will take up
|
||||||
|
* 14 bytes of message buffer space. The maximum number of bytes that can be
|
||||||
|
* stored in the message buffer is actually (xBufferSizeBytes - 1).
|
||||||
|
*
|
||||||
|
* @param pucMessageBufferStorageArea Must point to a uint8_t array that is at
|
||||||
|
* least xBufferSizeBytes + 1 big. This is the array to which messages are
|
||||||
|
* copied when they are written to the message buffer.
|
||||||
|
*
|
||||||
|
* @param pxStaticMessageBuffer Must point to a variable of type
|
||||||
|
* StaticMessageBuffer_t, which will be used to hold the message buffer's data
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* @return If the message buffer is created successfully then a handle to the
|
||||||
|
* created message buffer is returned. If either pucMessageBufferStorageArea or
|
||||||
|
* pxStaticmessageBuffer are NULL then NULL is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* // Used to dimension the array used to hold the messages. The available space
|
||||||
|
* // will actually be one less than this, so 999.
|
||||||
|
#define STORAGE_SIZE_BYTES 1000
|
||||||
|
*
|
||||||
|
* // Defines the memory that will actually hold the messages within the message
|
||||||
|
* // buffer.
|
||||||
|
* static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
|
||||||
|
*
|
||||||
|
* // The variable used to hold the message buffer structure.
|
||||||
|
* StaticMessageBuffer_t xMessageBufferStruct;
|
||||||
|
*
|
||||||
|
* void MyFunction( void )
|
||||||
|
* {
|
||||||
|
* MessageBufferHandle_t xMessageBuffer;
|
||||||
|
*
|
||||||
|
* xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ),
|
||||||
|
* ucBufferStorage,
|
||||||
|
* &xMessageBufferStruct );
|
||||||
|
*
|
||||||
|
* // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
|
||||||
|
* // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
|
||||||
|
* // reference the created message buffer in other message buffer API calls.
|
||||||
|
*
|
||||||
|
* // Other code that uses the message buffer can go here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
|
||||||
|
( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* const void *pvTxData,
|
||||||
|
* size_t xDataLengthBytes,
|
||||||
|
* TickType_t xTicksToWait );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Sends a discrete message to the message buffer. The message can be any
|
||||||
|
* length that fits within the buffer's free space, and is copied into the
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must place each call to a writing API function
|
||||||
|
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||||
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
|
* then the application writer must place each call to a reading API function
|
||||||
|
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||||
|
* block time to 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferSend() to write to a message buffer from a task. Use
|
||||||
|
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
|
||||||
|
* service routine (ISR).
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer to which a message is
|
||||||
|
* being sent.
|
||||||
|
*
|
||||||
|
* @param pvTxData A pointer to the message that is to be copied into the
|
||||||
|
* message buffer.
|
||||||
|
*
|
||||||
|
* @param xDataLengthBytes The length of the message. That is, the number of
|
||||||
|
* bytes to copy from pvTxData into the message buffer. When a message is
|
||||||
|
* written to the message buffer an additional sizeof( size_t ) bytes are also
|
||||||
|
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
|
||||||
|
* on a 32-bit architecture, so on most 32-bit architecture setting
|
||||||
|
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
|
||||||
|
* bytes (20 bytes of message data and 4 bytes to hold the message length).
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time the calling task should remain
|
||||||
|
* in the Blocked state to wait for enough space to become available in the
|
||||||
|
* message buffer, should the message buffer have insufficient space when
|
||||||
|
* xMessageBufferSend() is called. The calling task will never block if
|
||||||
|
* xTicksToWait is zero. The block time is specified in tick periods, so the
|
||||||
|
* absolute time it represents is dependent on the tick frequency. The macro
|
||||||
|
* pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
|
||||||
|
* a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause
|
||||||
|
* the task to wait indefinitely (without timing out), provided
|
||||||
|
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
|
||||||
|
* CPU time when they are in the Blocked state.
|
||||||
|
*
|
||||||
|
* @return The number of bytes written to the message buffer. If the call to
|
||||||
|
* xMessageBufferSend() times out before there was enough space to write the
|
||||||
|
* message into the message buffer then zero is returned. If the call did not
|
||||||
|
* time out then xDataLengthBytes is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* <pre>
|
||||||
|
* void vAFunction( MessageBufferHandle_t xMessageBuffer )
|
||||||
|
* {
|
||||||
|
* size_t xBytesSent;
|
||||||
|
* uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
|
||||||
|
* char *pcStringToSend = "String to send";
|
||||||
|
* const TickType_t x100ms = pdMS_TO_TICKS( 100 );
|
||||||
|
*
|
||||||
|
* // Send an array to the message buffer, blocking for a maximum of 100ms to
|
||||||
|
* // wait for enough space to be available in the message buffer.
|
||||||
|
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
|
||||||
|
*
|
||||||
|
* if( xBytesSent != sizeof( ucArrayToSend ) )
|
||||||
|
* {
|
||||||
|
* // The call to xMessageBufferSend() times out before there was enough
|
||||||
|
* // space in the buffer for the data to be written.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Send the string to the message buffer. Return immediately if there is
|
||||||
|
* // not enough space in the buffer.
|
||||||
|
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
|
||||||
|
*
|
||||||
|
* if( xBytesSent != strlen( pcStringToSend ) )
|
||||||
|
* {
|
||||||
|
* // The string could not be added to the message buffer because there was
|
||||||
|
* // not enough free space in the buffer.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xMessageBufferSend xMessageBufferSend
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \
|
||||||
|
xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* const void *pvTxData,
|
||||||
|
* size_t xDataLengthBytes,
|
||||||
|
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Interrupt safe version of the API function that sends a discrete message to
|
||||||
|
* the message buffer. The message can be any length that fits within the
|
||||||
|
* buffer's free space, and is copied into the buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must place each call to a writing API function
|
||||||
|
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||||
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
|
* then the application writer must place each call to a reading API function
|
||||||
|
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||||
|
* block time to 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferSend() to write to a message buffer from a task. Use
|
||||||
|
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
|
||||||
|
* service routine (ISR).
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer to which a message is
|
||||||
|
* being sent.
|
||||||
|
*
|
||||||
|
* @param pvTxData A pointer to the message that is to be copied into the
|
||||||
|
* message buffer.
|
||||||
|
*
|
||||||
|
* @param xDataLengthBytes The length of the message. That is, the number of
|
||||||
|
* bytes to copy from pvTxData into the message buffer. When a message is
|
||||||
|
* written to the message buffer an additional sizeof( size_t ) bytes are also
|
||||||
|
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
|
||||||
|
* on a 32-bit architecture, so on most 32-bit architecture setting
|
||||||
|
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
|
||||||
|
* bytes (20 bytes of message data and 4 bytes to hold the message length).
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
|
||||||
|
* have a task blocked on it waiting for data. Calling
|
||||||
|
* xMessageBufferSendFromISR() can make data available, and so cause a task that
|
||||||
|
* was waiting for data to leave the Blocked state. If calling
|
||||||
|
* xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
|
||||||
|
* unblocked task has a priority higher than the currently executing task (the
|
||||||
|
* task that was interrupted), then, internally, xMessageBufferSendFromISR()
|
||||||
|
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
|
||||||
|
* xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
|
||||||
|
* context switch should be performed before the interrupt is exited. This will
|
||||||
|
* ensure that the interrupt returns directly to the highest priority Ready
|
||||||
|
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
|
||||||
|
* is passed into the function. See the code example below for an example.
|
||||||
|
*
|
||||||
|
* @return The number of bytes actually written to the message buffer. If the
|
||||||
|
* message buffer didn't have enough free space for the message to be stored
|
||||||
|
* then 0 is returned, otherwise xDataLengthBytes is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* <pre>
|
||||||
|
* // A message buffer that has already been created.
|
||||||
|
* MessageBufferHandle_t xMessageBuffer;
|
||||||
|
*
|
||||||
|
* void vAnInterruptServiceRoutine( void )
|
||||||
|
* {
|
||||||
|
* size_t xBytesSent;
|
||||||
|
* char *pcStringToSend = "String to send";
|
||||||
|
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||||
|
*
|
||||||
|
* // Attempt to send the string to the message buffer.
|
||||||
|
* xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
|
||||||
|
* ( void * ) pcStringToSend,
|
||||||
|
* strlen( pcStringToSend ),
|
||||||
|
* &xHigherPriorityTaskWoken );
|
||||||
|
*
|
||||||
|
* if( xBytesSent != strlen( pcStringToSend ) )
|
||||||
|
* {
|
||||||
|
* // The string could not be added to the message buffer because there was
|
||||||
|
* // not enough free space in the buffer.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||||
|
* // xMessageBufferSendFromISR() then a task that has a priority above the
|
||||||
|
* // priority of the currently executing task was unblocked and a context
|
||||||
|
* // switch should be performed to ensure the ISR returns to the unblocked
|
||||||
|
* // task. In most FreeRTOS ports this is done by simply passing
|
||||||
|
* // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
|
||||||
|
* // variables value, and perform the context switch if necessary. Check the
|
||||||
|
* // documentation for the port in use for port specific instructions.
|
||||||
|
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* void *pvRxData,
|
||||||
|
* size_t xBufferLengthBytes,
|
||||||
|
* TickType_t xTicksToWait );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Receives a discrete message from a message buffer. Messages can be of
|
||||||
|
* variable length and are copied out of the buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must place each call to a writing API function
|
||||||
|
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||||
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
|
* then the application writer must place each call to a reading API function
|
||||||
|
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||||
|
* block time to 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
|
||||||
|
* xMessageBufferReceiveFromISR() to read from a message buffer from an
|
||||||
|
* interrupt service routine (ISR).
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer from which a message
|
||||||
|
* is being received.
|
||||||
|
*
|
||||||
|
* @param pvRxData A pointer to the buffer into which the received message is
|
||||||
|
* to be copied.
|
||||||
|
*
|
||||||
|
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
|
||||||
|
* parameter. This sets the maximum length of the message that can be received.
|
||||||
|
* If xBufferLengthBytes is too small to hold the next message then the message
|
||||||
|
* will be left in the message buffer and 0 will be returned.
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time the task should remain in the
|
||||||
|
* Blocked state to wait for a message, should the message buffer be empty.
|
||||||
|
* xMessageBufferReceive() will return immediately if xTicksToWait is zero and
|
||||||
|
* the message buffer is empty. The block time is specified in tick periods, so
|
||||||
|
* the absolute time it represents is dependent on the tick frequency. The
|
||||||
|
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
|
||||||
|
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
|
||||||
|
* cause the task to wait indefinitely (without timing out), provided
|
||||||
|
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
|
||||||
|
* CPU time when they are in the Blocked state.
|
||||||
|
*
|
||||||
|
* @return The length, in bytes, of the message read from the message buffer, if
|
||||||
|
* any. If xMessageBufferReceive() times out before a message became available
|
||||||
|
* then zero is returned. If the length of the message is greater than
|
||||||
|
* xBufferLengthBytes then the message will be left in the message buffer and
|
||||||
|
* zero is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* <pre>
|
||||||
|
* void vAFunction( MessageBuffer_t xMessageBuffer )
|
||||||
|
* {
|
||||||
|
* uint8_t ucRxData[ 20 ];
|
||||||
|
* size_t xReceivedBytes;
|
||||||
|
* const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
|
||||||
|
*
|
||||||
|
* // Receive the next message from the message buffer. Wait in the Blocked
|
||||||
|
* // state (so not using any CPU processing time) for a maximum of 100ms for
|
||||||
|
* // a message to become available.
|
||||||
|
* xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
|
||||||
|
* ( void * ) ucRxData,
|
||||||
|
* sizeof( ucRxData ),
|
||||||
|
* xBlockTime );
|
||||||
|
*
|
||||||
|
* if( xReceivedBytes > 0 )
|
||||||
|
* {
|
||||||
|
* // A ucRxData contains a message that is xReceivedBytes long. Process
|
||||||
|
* // the message here....
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xMessageBufferReceive xMessageBufferReceive
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \
|
||||||
|
xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait )
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* void *pvRxData,
|
||||||
|
* size_t xBufferLengthBytes,
|
||||||
|
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* An interrupt safe version of the API function that receives a discrete
|
||||||
|
* message from a message buffer. Messages can be of variable length and are
|
||||||
|
* copied out of the buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must place each call to a writing API function
|
||||||
|
* (such as xMessageBufferSend()) inside a critical section and set the send
|
||||||
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
|
* then the application writer must place each call to a reading API function
|
||||||
|
* (such as xMessageBufferRead()) inside a critical section and set the receive
|
||||||
|
* block time to 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
|
||||||
|
* xMessageBufferReceiveFromISR() to read from a message buffer from an
|
||||||
|
* interrupt service routine (ISR).
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer from which a message
|
||||||
|
* is being received.
|
||||||
|
*
|
||||||
|
* @param pvRxData A pointer to the buffer into which the received message is
|
||||||
|
* to be copied.
|
||||||
|
*
|
||||||
|
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
|
||||||
|
* parameter. This sets the maximum length of the message that can be received.
|
||||||
|
* If xBufferLengthBytes is too small to hold the next message then the message
|
||||||
|
* will be left in the message buffer and 0 will be returned.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
|
||||||
|
* have a task blocked on it waiting for space to become available. Calling
|
||||||
|
* xMessageBufferReceiveFromISR() can make space available, and so cause a task
|
||||||
|
* that is waiting for space to leave the Blocked state. If calling
|
||||||
|
* xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
|
||||||
|
* the unblocked task has a priority higher than the currently executing task
|
||||||
|
* (the task that was interrupted), then, internally,
|
||||||
|
* xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
|
||||||
|
* If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
|
||||||
|
* context switch should be performed before the interrupt is exited. That will
|
||||||
|
* ensure the interrupt returns directly to the highest priority Ready state
|
||||||
|
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
|
||||||
|
* passed into the function. See the code example below for an example.
|
||||||
|
*
|
||||||
|
* @return The length, in bytes, of the message read from the message buffer, if
|
||||||
|
* any.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* <pre>
|
||||||
|
* // A message buffer that has already been created.
|
||||||
|
* MessageBuffer_t xMessageBuffer;
|
||||||
|
*
|
||||||
|
* void vAnInterruptServiceRoutine( void )
|
||||||
|
* {
|
||||||
|
* uint8_t ucRxData[ 20 ];
|
||||||
|
* size_t xReceivedBytes;
|
||||||
|
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||||
|
*
|
||||||
|
* // Receive the next message from the message buffer.
|
||||||
|
* xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
|
||||||
|
* ( void * ) ucRxData,
|
||||||
|
* sizeof( ucRxData ),
|
||||||
|
* &xHigherPriorityTaskWoken );
|
||||||
|
*
|
||||||
|
* if( xReceivedBytes > 0 )
|
||||||
|
* {
|
||||||
|
* // A ucRxData contains a message that is xReceivedBytes long. Process
|
||||||
|
* // the message here....
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||||
|
* // xMessageBufferReceiveFromISR() then a task that has a priority above the
|
||||||
|
* // priority of the currently executing task was unblocked and a context
|
||||||
|
* // switch should be performed to ensure the ISR returns to the unblocked
|
||||||
|
* // task. In most FreeRTOS ports this is done by simply passing
|
||||||
|
* // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
|
||||||
|
* // variables value, and perform the context switch if necessary. Check the
|
||||||
|
* // documentation for the port in use for port specific instructions.
|
||||||
|
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Deletes a message buffer that was previously created using a call to
|
||||||
|
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
|
||||||
|
* buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
|
||||||
|
* then the allocated memory is freed.
|
||||||
|
*
|
||||||
|
* A message buffer handle must not be used after the message buffer has been
|
||||||
|
* deleted.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer to be deleted.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define vMessageBufferDelete( xMessageBuffer ) \
|
||||||
|
vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Tests to see if a message buffer is full. A message buffer is full if it
|
||||||
|
* cannot accept any more messages, of any size, until space is made available
|
||||||
|
* by a message being removed from the message buffer.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return If the message buffer referenced by xMessageBuffer is full then
|
||||||
|
* pdTRUE is returned. Otherwise pdFALSE is returned.
|
||||||
|
*/
|
||||||
|
#define xMessageBufferIsFull( xMessageBuffer ) \
|
||||||
|
xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Tests to see if a message buffer is empty (does not contain any messages).
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return If the message buffer referenced by xMessageBuffer is empty then
|
||||||
|
* pdTRUE is returned. Otherwise pdFALSE is returned.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define xMessageBufferIsEmpty( xMessageBuffer ) \
|
||||||
|
xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Resets a message buffer to its initial empty state, discarding any message it
|
||||||
|
* contained.
|
||||||
|
*
|
||||||
|
* A message buffer can only be reset if there are no tasks blocked on it.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being reset.
|
||||||
|
*
|
||||||
|
* @return If the message buffer was reset then pdPASS is returned. If the
|
||||||
|
* message buffer could not be reset because either there was a task blocked on
|
||||||
|
* the message queue to wait for space to become available, or to wait for a
|
||||||
|
* a message to be available, then pdFAIL is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferReset xMessageBufferReset
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReset( xMessageBuffer ) \
|
||||||
|
xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* <pre>
|
||||||
|
* size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
|
||||||
|
* </pre>
|
||||||
|
* Returns the number of bytes of free space in the message buffer.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return The number of bytes that can be written to the message buffer before
|
||||||
|
* the message buffer would be full. When a message is written to the message
|
||||||
|
* buffer an additional sizeof( size_t ) bytes are also written to store the
|
||||||
|
* message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||||
|
* architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
|
||||||
|
* of the largest message that can be written to the message buffer is 6 bytes.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSpaceAvailable( xMessageBuffer ) \
|
||||||
|
xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer )
|
||||||
|
#define xMessageBufferSpacesAvailable( xMessageBuffer ) \
|
||||||
|
xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* <pre>
|
||||||
|
* size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) );
|
||||||
|
* </pre>
|
||||||
|
* Returns the length (in bytes) of the next message in a message buffer.
|
||||||
|
* Useful if xMessageBufferReceive() returned 0 because the size of the buffer
|
||||||
|
* passed into xMessageBufferReceive() was too small to hold the next message.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return The length (in bytes) of the next message in the message buffer, or 0
|
||||||
|
* if the message buffer is empty.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferNextLengthBytes( xMessageBuffer ) \
|
||||||
|
xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* For advanced users only.
|
||||||
|
*
|
||||||
|
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||||
|
* data is sent to a message buffer or stream buffer. If there was a task that
|
||||||
|
* was blocked on the message or stream buffer waiting for data to arrive then
|
||||||
|
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
|
||||||
|
* from the Blocked state. xMessageBufferSendCompletedFromISR() does the same
|
||||||
|
* thing. It is provided to enable application writers to implement their own
|
||||||
|
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
|
||||||
|
*
|
||||||
|
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||||
|
* additional information.
|
||||||
|
*
|
||||||
|
* @param xStreamBuffer The handle of the stream buffer to which data was
|
||||||
|
* written.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||||
|
* initialised to pdFALSE before it is passed into
|
||||||
|
* xMessageBufferSendCompletedFromISR(). If calling
|
||||||
|
* xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
|
||||||
|
* and the task has a priority above the priority of the currently running task,
|
||||||
|
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||||
|
* context switch should be performed before exiting the ISR.
|
||||||
|
*
|
||||||
|
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||||
|
* Otherwise pdFALSE is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
|
||||||
|
* \ingroup StreamBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* For advanced users only.
|
||||||
|
*
|
||||||
|
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||||
|
* data is read out of a message buffer or stream buffer. If there was a task
|
||||||
|
* that was blocked on the message or stream buffer waiting for data to arrive
|
||||||
|
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
|
||||||
|
* remove it from the Blocked state. xMessageBufferReceiveCompletedFromISR()
|
||||||
|
* does the same thing. It is provided to enable application writers to
|
||||||
|
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
|
||||||
|
* ANY OTHER TIME.
|
||||||
|
*
|
||||||
|
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||||
|
* additional information.
|
||||||
|
*
|
||||||
|
* @param xStreamBuffer The handle of the stream buffer from which data was
|
||||||
|
* read.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||||
|
* initialised to pdFALSE before it is passed into
|
||||||
|
* xMessageBufferReceiveCompletedFromISR(). If calling
|
||||||
|
* xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
|
||||||
|
* and the task has a priority above the priority of the currently running task,
|
||||||
|
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||||
|
* context switch should be performed before exiting the ISR.
|
||||||
|
*
|
||||||
|
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||||
|
* Otherwise pdFALSE is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
|
||||||
|
* \ingroup StreamBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken )
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#if defined( __cplusplus )
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.4.3
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the MPU is used the standard (non MPU) API functions are mapped to
|
||||||
|
* equivalents that start "MPU_", the prototypes for which are defined in this
|
||||||
|
* header files. This will cause the application code to call the MPU_ version
|
||||||
|
* which wraps the non-MPU version with privilege promoting then demoting code,
|
||||||
|
* so the kernel code always runs will full privileges.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MPU_PROTOTYPES_H
|
||||||
|
#define MPU_PROTOTYPES_H
|
||||||
|
|
||||||
|
/* MPU versions of tasks.h API functions. */
|
||||||
|
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const uint16_t usStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const uint32_t ulStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
StackType_t * const puxStackBuffer,
|
||||||
|
StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
|
||||||
|
const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskGetInfo( TaskHandle_t xTask,
|
||||||
|
TaskStatus_t * pxTaskStatus,
|
||||||
|
BaseType_t xGetFreeStackSpace,
|
||||||
|
eTaskState eState ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskPrioritySet( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask,
|
||||||
|
TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
|
||||||
|
BaseType_t xIndex,
|
||||||
|
void * pvValue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
|
||||||
|
BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
|
||||||
|
void * pvParameter ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
||||||
|
const UBaseType_t uxArraySize,
|
||||||
|
uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
|
||||||
|
UBaseType_t uxIndexToNotify,
|
||||||
|
uint32_t ulValue,
|
||||||
|
eNotifyAction eAction,
|
||||||
|
uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
|
||||||
|
uint32_t ulBitsToClearOnEntry,
|
||||||
|
uint32_t ulBitsToClearOnExit,
|
||||||
|
uint32_t * pulNotificationValue,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
|
||||||
|
BaseType_t xClearCountOnExit,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxIndexToClear,
|
||||||
|
uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
||||||
|
TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* MPU versions of queue.h API functions. */
|
||||||
|
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue,
|
||||||
|
const void * const pvItemToQueue,
|
||||||
|
TickType_t xTicksToWait,
|
||||||
|
const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue,
|
||||||
|
void * const pvBuffer,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue,
|
||||||
|
void * const pvBuffer,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
|
||||||
|
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
|
||||||
|
const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
|
||||||
|
const UBaseType_t uxInitialCount,
|
||||||
|
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue,
|
||||||
|
const char * pcName ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
|
||||||
|
const UBaseType_t uxItemSize,
|
||||||
|
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
|
||||||
|
const UBaseType_t uxItemSize,
|
||||||
|
uint8_t * pucQueueStorage,
|
||||||
|
StaticQueue_t * pxStaticQueue,
|
||||||
|
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||||
|
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||||
|
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
|
||||||
|
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
|
||||||
|
BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue,
|
||||||
|
UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* MPU versions of timers.h API functions. */
|
||||||
|
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName,
|
||||||
|
const TickType_t xTimerPeriodInTicks,
|
||||||
|
const UBaseType_t uxAutoReload,
|
||||||
|
void * const pvTimerID,
|
||||||
|
TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName,
|
||||||
|
const TickType_t xTimerPeriodInTicks,
|
||||||
|
const UBaseType_t uxAutoReload,
|
||||||
|
void * const pvTimerID,
|
||||||
|
TimerCallbackFunction_t pxCallbackFunction,
|
||||||
|
StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTimerSetTimerID( TimerHandle_t xTimer,
|
||||||
|
void * pvNewID ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
|
||||||
|
void * pvParameter1,
|
||||||
|
uint32_t ulParameter2,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer,
|
||||||
|
const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer,
|
||||||
|
const BaseType_t xCommandID,
|
||||||
|
const TickType_t xOptionalValue,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||||
|
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* MPU versions of event_group.h API functions. */
|
||||||
|
EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* MPU versions of message/stream_buffer.h API functions. */
|
||||||
|
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
const void * pvTxData,
|
||||||
|
size_t xDataLengthBytes,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
void * pvRxData,
|
||||||
|
size_t xBufferLengthBytes,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
|
||||||
|
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
|
||||||
|
size_t xTriggerLevelBytes,
|
||||||
|
BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
|
||||||
|
size_t xTriggerLevelBytes,
|
||||||
|
BaseType_t xIsMessageBuffer,
|
||||||
|
uint8_t * const pucStreamBufferStorageArea,
|
||||||
|
StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MPU_PROTOTYPES_H */
|
||||||
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user