Compare commits

...
413 Commits
Author SHA1 Message Date
Sergio R. Caprile 4236405b90 Ready to release 2023-01-24 13:30:45 -03:00
Sergio R. Caprile 292c66e25c Merge pull request #1992 from cesanta/revert-1920-patch-1
Revert "Update comment for the path of rest API"
2023-01-24 11:42:18 -03:00
Sergio R. Caprile 5aa6c15c76 Revert "Update comment for the path of rest API" 2023-01-24 11:41:51 -03:00
Sergio R. Caprile 1f89dc47cb Merge pull request #1991 from cesanta/revert-1797-fix-typo
Revert "Fix typo in documentation"
2023-01-24 11:36:51 -03:00
Sergio R. Caprile 31393128c8 Revert "Fix typo in documentation" 2023-01-24 11:35:26 -03:00
Sergio R. Caprile 232a18425a Merge pull request #1990 from cesanta/revert-1705-master
Revert "fix the doc error: htts to https"
2023-01-24 11:33:02 -03:00
Sergio R. Caprile 88e2eb2a49 Revert "fix the doc error: htts to https" 2023-01-24 11:31:25 -03:00
Sergey Lyubka e635d5f748 Merge pull request #1986 from cesanta/w5
Add examples/rp2040/pico-w5500 to hwtest
2023-01-23 12:32:14 +00:00
Sergey Lyubka 08a23cdb2f Merge pull request #1988 from cesanta/h743
Add nucleo-h743zi-baremetal boilerplate, with HW test
2023-01-23 12:31:55 +00:00
cpq 1ead940623 Add nucleo-h743zi-baremetal boilerplate, with HW test 2023-01-22 11:48:56 +00:00
cpq 987f8bc949 Prep for msc 2023-01-21 13:42:25 +00:00
cpq 6f096333d3 make clean: invoke docker only when there is something to clean 2023-01-21 07:44:50 +00:00
cpq 5a25111b20 Add examples/rp2040/pico-w5500 to hwtest 2023-01-21 02:21:20 +00:00
Sergio R. Caprile c7cb16cafa Merge pull request #1984 from cesanta/ti-nodocker
Get rid of Docker (TI), part 2: FreeRTOS
2023-01-20 18:47:55 -03:00
Sergio R. Caprile a746a698b6 Merge pull request #1983 from cesanta/stm32-nodocker
Get rid of Docker, part 2: FreeRTOS
2023-01-20 18:47:27 -03:00
Sergio R. Caprile 9a7f7255ff Get rid of Docker, part 2: FreeRTOS 2023-01-20 18:20:19 -03:00
Sergio R. Caprile d3df6b8f4f Get rid of Docker (TI), part 2: FreeRTOS 2023-01-20 18:19:29 -03:00
Sergio R. Caprile fcffd17b11 Merge pull request #1982 from cesanta/freertos
Fix FreeRTOS arch includes on newlib platforms
2023-01-20 18:16:55 -03:00
Sergio R. Caprile 7fc6be9f39 Fix FreeRTOS arch includes on newlib platforms 2023-01-20 18:09:21 -03:00
Sergio R. Caprile 7362744ff8 Merge pull request #1981 from cesanta/stm32uarts
Fix UART1,2 clocking in all other examples
2023-01-20 18:00:46 -03:00
Sergio R. Caprile f4d058155a Fix UART1,2 clocking in all other examples 2023-01-20 17:49:57 -03:00
Sergio R. Caprile b04612e80d Merge pull request #1975 from cesanta/hwtest
Cleanup, adopt for HW test
2023-01-20 16:26:05 -03:00
Sergio R. Caprile 5f00e4d34d Merge pull request #1980 from cesanta/ti-nodocker
Get rid of Docker (TI), part 1
2023-01-20 16:21:45 -03:00
cpq e967feb091 Cleanup, adopt for HW test 2023-01-20 18:46:19 +00:00
Sergio R. Caprile 0445b18bb9 Merge pull request #1977 from cesanta/reallyclean
Apply a deeper cleanser
2023-01-20 15:36:51 -03:00
Sergio R. Caprile 99f1f749cf Apply a deeper cleanser 2023-01-20 15:27:37 -03:00
Sergio R. Caprile f4d16f1c47 Get rid of Docker (TI), part 1 2023-01-20 15:06:03 -03:00
Sergio R. Caprile 68071d6caf Merge pull request #1976 from cesanta/stm32-nodocker
Get rid of Docker, part 1
2023-01-20 14:14:07 -03:00
Sergio R. Caprile 44975da7db Get rid of Docker, part 1 2023-01-20 12:42:38 -03:00
Sergio R. Caprile e4566518b2 Merge pull request #1978 from cesanta/test-nosprintf
Make MacOS happy by getting rid of sprintf()
2023-01-20 12:41:09 -03:00
novlean c038cb5b96 Merge pull request #1979 from cesanta/novlean-patch-1
2023
2023-01-20 15:31:07 +00:00
novlean d7eb3db60b 2023 2023-01-20 15:28:16 +00:00
Sergio R. Caprile 44e781d7da Make MacOS happy be getting rid of sprintf() 2023-01-20 11:54:56 -03:00
Sergio R. Caprile 0951d58c8f Merge pull request #1974 from cesanta/stm32uarts
Fix AF in UART1,2
2023-01-19 16:31:55 -03:00
Sergio R. Caprile 37c0ed0b49 Fix AF in UART1,2 2023-01-19 15:28:51 -03:00
cpq 556bf7b888 Fix uart_init(), use correct AF for UART1/UART2 2023-01-19 10:31:26 +00:00
Sergey Lyubka 280be2eaea Merge pull request #1968 from cesanta/ackstream
Don't retrigger ACK timer
2023-01-18 08:52:12 +00:00
Sergio R. Caprile 13f9357f8e Merge pull request #1970 from cesanta/test-pico-rndis
Update test.yml
2023-01-17 15:19:45 -03:00
Sergio R. Caprile 56e015db0e Enable test for pico-rndis-dashboard 2023-01-17 14:58:05 -03:00
Sergio R. Caprile 1068fbf079 Merge pull request #1969 from cesanta/pico-dash
Simplify build
2023-01-17 13:59:54 -03:00
Sergio R. Caprile 45f7afb3e1 Simplify build 2023-01-17 13:54:22 -03:00
Sergio R. Caprile 0d3fc2b656 Don't retrigger ACK timer 2023-01-16 20:16:59 -03:00
Sergio R. Caprile 2dc66b2e3b Merge pull request #1966 from cesanta/test-pico-rmii
Update test.yml
2023-01-16 16:48:10 -03:00
Sergio R. Caprile 0b9129d8f5 Update test.yml 2023-01-16 15:36:50 -03:00
cpq 82d702fedc mg_url_encode() 0-terminate the destination 2023-01-16 15:05:04 +00:00
Sergey Lyubka 197be75677 Merge pull request #1960 from cesanta/keepalive
TCP keepalives
2023-01-16 10:40:28 +00:00
cpq 3f9aff1b10 Update uart logs with Ethernet status 2023-01-15 12:03:40 +00:00
Sergey Lyubka f5ed50fa88 Merge pull request #1959 from cesanta/handle-rst
Handle TCP RST
2023-01-14 00:16:40 +00:00
Sergio R. Caprile 645b52602f Update main.c 2023-01-13 15:08:00 -03:00
Sergio R. Caprile 27a8e60e9a TCP keepalives 2023-01-12 15:58:25 -03:00
Sergio R. Caprile 201ffa108b Handle TCP RST 2023-01-11 17:33:37 -03:00
Sergey Lyubka 1661bd6691 Merge pull request #1955 from cesanta/picormii
Add RMII example for RP2040
2023-01-11 10:40:10 +00:00
Sergio R. Caprile d431f4bbc5 Merge pull request #1957 from cesanta/pico-w5500
updated to ARCH_RP2040
2023-01-10 11:21:23 -03:00
Sergio R. Caprile 2b8e92a70d updated to ARCH_RP2040 2023-01-10 10:54:27 -03:00
Sergey Lyubka d70ab3cfa8 Merge pull request #1944 from cesanta/devdash
Add reduced functionality version
2023-01-10 12:31:03 +00:00
Sergey Lyubka 9402c6ad28 Merge pull request #1956 from cesanta/lbl
Rename struct mg_connection::label -> data. Make its size configurable
2023-01-10 08:34:22 +00:00
cpq da5e8e9778 Rename struct mg_connection::label -> data. Make its size configurable 2023-01-10 08:19:49 +00:00
Sergio R. Caprile feedfdf810 Update main.c 2023-01-09 14:31:04 -03:00
Sergio R. Caprile 6db0a502bf Add RMII example 2023-01-09 11:16:01 -03:00
Sergey Lyubka f07957d45e Merge pull request #1952 from cesanta/mipqueue
Rename mip_rxcb to mip_qwrite, add mip_qread and enforce rx() for drivers
2023-01-08 06:47:38 +00:00
cpq 3d75d71767 Do not show response handler in the rpc.list result 2023-01-08 06:38:08 +00:00
Sergio R. Caprile b259bdeddd Rename mip_rxcb to mip_qwrite, add mip_qread and enforce rx() for drivers 2023-01-03 19:33:26 -03:00
Sergey Lyubka 042465387f Merge pull request #1950 from cesanta/picodash
Add Pico dashboard
2023-01-02 20:14:34 +00:00
Sergio R. Caprile d09e4d648c Add Pico dashboard 2023-01-02 16:49:15 -03:00
Sergio R. Caprile 754910ad5f Merge pull request #1947 from cesanta/pico
Moved pico-w example
2023-01-02 15:48:24 -03:00
Sergio R. Caprile 977e080215 Update test.yml 2023-01-02 15:29:21 -03:00
Sergio R. Caprile a9ac947c96 Merge pull request #1949 from cesanta/scaprile-patch-1
Update test.yml
2023-01-02 15:23:15 -03:00
Sergio R. Caprile 28e6ef1d63 Update test.yml 2023-01-02 15:22:24 -03:00
Sergio R. Caprile b0f273157d Fix Makefile 2023-01-02 15:16:50 -03:00
Sergio R. Caprile 49add531c4 Moved pico-w example 2023-01-02 15:12:07 -03:00
cpq 8a1d2a5dca Install gcc-arm-none-eabi for examples 2023-01-02 17:53:55 +00:00
Sergey Lyubka 31c5883f5f Merge pull request #1946 from cesanta/rp2040-w5500
Add pico-w5500 example
2023-01-02 16:48:43 +00:00
Sergey Lyubka c625fbb43d Merge branch 'master' into rp2040-w5500 2023-01-02 16:48:34 +00:00
cpq 0f474e8d2a Add pico-w5500 example 2023-01-02 16:36:55 +00:00
Sergey Lyubka 73813a8383 Merge pull request #1943 from cesanta/add-test-for-RNDIS-examples
Update tests
2022-12-28 02:47:56 +00:00
Sergio R. Caprile d8fb110b56 Update test.yml 2022-12-27 20:34:10 -03:00
Sergio R. Caprile 77e62626a9 Add RNDIS examples to tests, remove "stm32/nucleo*" examples from "examples" test group 2022-12-27 20:27:08 -03:00
Sergio R. Caprile 24ee83f13d Update test.yml 2022-12-27 18:31:39 -03:00
Sergio R. Caprile 6791a36d85 Add reduced functionality version 2022-12-27 18:12:55 -03:00
Sergio R. Caprile c6a5a64e64 Update test.yml 2022-12-26 10:51:44 -03:00
Sergey Lyubka 311062dc41 Merge pull request #1938 from cesanta/F746rndis
Add RNDIS example for F7
2022-12-24 15:10:00 +00:00
Sergio R. Caprile 391ce1f009 Merge pull request #1939 from cesanta/tireadme
Added link to tutorial
2022-12-23 19:47:14 -03:00
Sergio R. Caprile 9f6d99352a Added link to tutorial 2022-12-23 19:45:57 -03:00
Sergio R. Caprile 02b1d6260a Add RNDIS example for F7 2022-12-23 19:28:33 -03:00
Sergio R. Caprile e8ade14259 Merge pull request #1937 from cesanta/tm4cdriverdata
Rename driver data structure
2022-12-23 16:27:42 -03:00
Sergio R. Caprile f0804dfed4 Merge pull request #1936 from cesanta/stm32driverdata
Rename driver data structure
2022-12-23 15:57:19 -03:00
Sergio R. Caprile f506344ada Rename driver data structure 2022-12-23 15:56:46 -03:00
Sergio R. Caprile ddca518cca Rename driver data structure 2022-12-23 15:45:30 -03:00
cpq 21d3678fa7 Add more on logging 2022-12-21 11:31:14 +00:00
cpq 3dd8d7d8e5 Add diagrams 2022-12-21 11:18:50 +00:00
Sergio R. Caprile 92aa538a84 Merge pull request #1934 from cesanta/myheart
Unbreak
2022-12-20 19:39:22 -03:00
Sergio R. Caprile 557a5583e8 Unbreak 2022-12-20 19:38:20 -03:00
Sergio R. Caprile b00ddff7dd Merge pull request #1933 from cesanta/fixmqttserver
Fix MQTT server example
2022-12-20 16:08:56 -03:00
Sergio R. Caprile cc3b311ab0 Fix MQTT server example 2022-12-20 16:06:46 -03:00
cpq 6cedca5d76 Remove DS_Store 2022-12-19 14:40:17 +00:00
Sergey Lyubka d82452e00f Merge pull request #1929 from cesanta/usb
Add TinyUSB example
2022-12-19 14:33:11 +00:00
cpq 57a5c0ba38 Add TinyUSB example 2022-12-19 14:31:54 +00:00
Sergio R. Caprile 28c8519e5b Merge pull request #1924 from cesanta/scaprile-patch-1
Update README.md
2022-12-15 10:31:37 -03:00
Sergio R. Caprile cfcb7191ea Update README.md 2022-12-15 09:52:19 -03:00
Sergey Lyubka 6921227ec8 Merge pull request #1915 from jfsimon1981/miptap
Mip tests and tuntap example to compile on OpenBSD natively.
2022-12-13 16:42:09 +00:00
Sergey Lyubka 1c9991ee83 Merge pull request #1916 from cesanta/stm32
Minor tweaks in STM32 examples
2022-12-13 16:40:38 +00:00
Sergey Lyubka fd475fcfff Merge pull request #1917 from cesanta/tm4c
Correct stack initialization
2022-12-13 16:40:10 +00:00
Sergio R. Caprile f47f995e90 Merge pull request #1921 from cesanta/scaprile-patch-1
Update test.yml
2022-12-13 13:02:11 -03:00
Sergio R. Caprile d93e943326 Update test.yml 2022-12-13 12:51:43 -03:00
Sergio R. Caprile 7ca9f2d5cd Merge pull request #1920 from jojo2massol/patch-1
Update comment for the path of rest API
2022-12-13 12:39:28 -03:00
jojo2massol ff1d45a008 Update comment for the path of rest API
rest api is available at `/rest` and not `/api/rest`
2022-12-13 15:33:51 +01:00
Sergio R. Caprile 53f0a72362 Merge pull request #1919 from cesanta/doc1918
Update README.md
2022-12-10 20:14:30 -03:00
Sergio R. Caprile 3a47242219 Update README.md
Closes #1918
2022-12-10 20:12:58 -03:00
Jean-Francois Simon 5556568feb Mip tests and tuntap example to compile on OpenBSD natively.
(updated for c++ build)

Fix typo
2022-12-09 18:48:05 +00:00
Sergio R. Caprile 6011a15cd4 Correct stack initialization 2022-12-09 15:47:23 -03:00
Sergio R. Caprile 2c014778d9 Minor tweaks in STM32 examples
Fix comments in newer mip initialization (main.c)
Correct stack initialization (boot.c)
Remove SCC clock enable when not needed (mcu.h)
2022-12-09 15:20:51 -03:00
Sergey Lyubka 0b2712f52f Merge pull request #1911 from cesanta/gwarp
Ask for gw mac when needed and not known
2022-12-09 11:51:40 +00:00
Sergey Lyubka 69f1acd823 Merge pull request #1912 from cesanta/nodupack
Avoid duplicated ACKs
2022-12-09 11:50:30 +00:00
cpq c0f15d50d6 Squash cppcheck warn 2022-12-09 09:29:34 +00:00
Sergio R. Caprile 1d3fe51e8b Avoid duplicated ACKs 2022-12-08 18:59:18 -03:00
Sergio R. Caprile d364d50c05 Improve MIP resiliency 2022-12-08 17:17:05 -03:00
Sergey Lyubka 615d324b11 Merge pull request #1906 from jfsimon1981/armfix
Fix arm and armhf test builds and unit_test runtime.
2022-12-07 18:31:29 +00:00
Jean-Francois Simon eb36b6755f Fix arm and armhf test builds and unit_test runtime.
Generalized with the correct define (comment from SC).
2022-12-07 17:09:13 +00:00
Sergey Lyubka 40c28d3b21 Merge pull request #1905 from cesanta/percentA
Use %I in mip.c
2022-12-07 07:22:10 +00:00
Sergio R. Caprile e726282023 Merge pull request #1908 from cesanta/tm4creadme
Add README
2022-12-06 17:10:19 -03:00
Sergio R. Caprile 327f734e4f Add README 2022-12-06 17:09:15 -03:00
Sergio R. Caprile b361f64d4f Merge pull request #1907 from cesanta/tests
Update test.yml
2022-12-06 16:25:47 -03:00
Sergio R. Caprile b38d215b3d Update test.yml 2022-12-06 15:53:18 -03:00
Sergio R. Caprile 99aa498bc4 Use %I in mip.c
Add %A to print hw address and use it in mip.c
Fix some debug data
2022-12-06 13:44:31 -03:00
Sergio R. Caprile f14798dec9 Merge pull request #1904 from cesanta/tm4cdriver
Improve TM4C driver
2022-12-06 11:08:44 -03:00
Sergio R. Caprile 65873f3dee Improve TM4C driver
- Fix clock guessing
- Frames are now read in order, and only host owned descriptors are checked
- Read as many frames as possible (but don't loop forever)
- Discard bad frames
- Fixed incorrect handling of RU bit and exit out of suspended condition
- If a frame arrives while processing, it will now generate a new interrupt (formerly it would wait for another frame to arrive as we reset the flag on exit)
2022-12-06 10:45:41 -03:00
Sergio R. Caprile fc98c88358 Merge pull request #1903 from cesanta/freemgstrdupdoc
Update README.md
2022-12-05 16:30:24 -03:00
Sergio R. Caprile 7c0440c148 Update README.md 2022-12-05 16:24:28 -03:00
Sergio R. Caprile ad051269ed Merge pull request #1899 from cesanta/castREADME
Update README.md
2022-12-04 19:17:23 -03:00
Sergio R. Caprile 497d8f25a1 Update README.md 2022-12-04 19:16:34 -03:00
Sergey Lyubka eb142f26f2 Merge pull request #1897 from cesanta/i
Fix #1888: add %I *printf specifier for IP address. Remove mg_ntoa, m…
2022-12-03 14:39:47 +00:00
cpq b01989f041 Fix #1888: add %I *printf specifier for IP address. Remove mg_ntoa, mg_straddr 2022-12-03 14:27:07 +00:00
Sergey Lyubka 84d89e80cd Merge pull request #1896 from cesanta/stm32driver
Improve STM32 driver
2022-12-03 09:40:38 +00:00
Sergio R. Caprile d059d2cda4 Improve STM32 driver 2022-12-02 19:47:29 -03:00
jfsimon1981 751413f050 MIP tuntap with dhcp added, enabled gitactions (#1890)
Enable DHCP with MIP tests.
Separate sources for high and low level stack tests.
Fixed assertion.
Added dhcpd.conf file.
2022-12-02 17:40:46 +01:00
Sergey Lyubka ce5e28554f Merge pull request #1891 from cesanta/baremetalREADMEs
Add links to tool installation in MIP hw examples
2022-12-02 07:12:46 +00:00
Sergio R. Caprile 860be3f96c Add links to tool installation in MIP hw examples 2022-12-01 17:23:16 -03:00
Sergey Lyubka 89fb3a3d6e Merge pull request #1889 from cesanta/mippoll
MG_EV_POLL generation on MIP
2022-12-01 07:25:19 +00:00
Sergio R. Caprile 474a07564c Make test NOT fail 2022-11-30 18:16:13 -03:00
Sergio R. Caprile 59b69a3b3b Add test for MG_EV_POLL generation 2022-11-30 12:13:45 -03:00
Sergey Lyubka 2553392e42 Merge pull request #1885 from cesanta/tm4c-freertos-mip
Add FreeRTOS + MIP example on TM4C
2022-11-29 15:17:48 +00:00
cpq fcd6901558 Fix broken mip_test 2022-11-29 14:55:36 +00:00
Sergio R. Caprile 716ffbb945 Add FreeRTOS + MIP tutorial on TM4C 2022-11-29 11:16:43 -03:00
Sergey Lyubka cd4b9aeafe Merge pull request #1884 from cesanta/macfilter
Fix MAC address filtering on STM32 and TM4C
2022-11-29 14:05:11 +00:00
Sergey Lyubka 5d712b6f54 Merge pull request #1886 from jfsimon1981/master
Release MIP tests using tuntap
2022-11-29 11:24:52 +00:00
Jean-Francois Simon 754c68fccc Release MIP tests using tuntap 2022-11-29 11:20:22 +01:00
Sergio R. Caprile 858f4da0d1 Fix MAC address filtering on STM32 and TM4C 2022-11-28 10:16:10 -03:00
Sergey Lyubka 90910a7a4f Merge pull request #1883 from cesanta/arpbcast
Fix sending ARP request for IP broadcasts
2022-11-26 11:58:16 +00:00
Sergey Lyubka cd218b59f9 Merge pull request #1882 from cesanta/f746zg-frertos-mip
Add FreeRTOS + MIP example on F746
2022-11-26 11:57:43 +00:00
Sergio R. Caprile 9625c49c95 Fix sending ARP request for IP broadcasts 2022-11-25 17:42:35 -03:00
Sergio R. Caprile 2dfed10d2e Add FreeRTOS + MIP example on F746 2022-11-25 16:57:35 -03:00
cpq a74d3737dc Fix mip-pcap 2022-11-25 14:23:59 +00:00
cpq 6c82a34aa0 Remove unused code 2022-11-25 10:00:04 +00:00
cpq 320d5656ac Remove unused code 2022-11-25 10:00:04 +00:00
Sergio R. Caprile a4a5778001 Merge pull request #1879 from cesanta/freestdlib
Add stdlib.h to includes in FreeRTOS arch
2022-11-24 10:34:24 -03:00
Sergio R. Caprile a80a003865 Add stdlib.h to includes in FreeRTOS arch 2022-11-24 10:15:03 -03:00
cpq 4607e46c6f Disable mip_test on macos 2022-11-24 07:21:55 +00:00
cpq 0aa3e2e49c Enable macos test 2022-11-24 07:02:17 +00:00
Sergio R. Caprile 595bb36956 Merge pull request #1878 from cesanta/Makefile
be able to flash target
2022-11-23 17:09:05 -03:00
Sergio R. Caprile afdf7e6df3 actually be able to flash target 2022-11-23 16:13:37 -03:00
Sergey Lyubka 3e1c7d7ef2 Merge pull request #1874 from cesanta/makefix
Fix wildcard in Makefile
2022-11-23 10:16:11 +00:00
cpq 7ce7c3deb7 Fix mingw build 2022-11-22 09:50:35 +00:00
Sergio R. Caprile c9b390ec60 Fix wildcard in Makefile 2022-11-21 16:57:15 -03:00
Sergey Lyubka cc2b826356 Merge pull request #1865 from jfsimon1981/master
Implemented MIP stack http_fetch()
2022-11-21 18:35:14 +00:00
Jean-Francois Simon 0b2c493731 Merge branch 'master' of https://github.com/jfsimon1981/mongoose 2022-11-21 15:33:42 +01:00
Jean-Francois Simon 0d7bbc51e7 Implemented MIP stack http_fetch()
This approach used tuntap driver for Linux/Unices
2022-11-21 15:32:45 +01:00
Sergey Lyubka db81c30d24 Merge pull request #1871 from cesanta/straddr
Fix mg_straddr() stack overwrite
2022-11-21 07:00:23 +00:00
cpq 41ea8de0d6 Mark request close for HTTP redirects 2022-11-20 12:18:15 +00:00
Sergio R. Caprile c4b5b37568 Fix mg_straddr() stack overwrite 2022-11-19 19:44:52 -03:00
Sergio R. Caprile 76e6b23a4f Update README.md 2022-11-18 18:06:48 -03:00
Sergio R. Caprile 283e295a98 Merge pull request #1869 from cesanta/miptap
Add missing include
2022-11-18 12:28:59 -03:00
Sergio R. Caprile 606009afb0 Add missing include
linux/if uses struct sockaddr that is defined in sys/socket.h. This breaks building on some systems. It went unnoticed as it was hidden by mongoose.h being included first
2022-11-18 10:51:58 -03:00
Sergey Lyubka da303b8b4f Merge pull request #1858 from cesanta/LAA
change MIP MAC to LAA
2022-11-18 10:41:12 +00:00
Sergey Lyubka d4048661ae Merge pull request #1857 from cesanta/scaprile-patch-1
Update issue_template.md
2022-11-18 10:39:34 +00:00
Sergey Lyubka 47853547ca Merge pull request #1856 from cesanta/zephyr-tests
Zephyr tests
2022-11-18 10:39:13 +00:00
Jean-Francois Simon 6ae9188af4 Implemented MIP stack http_fetch()
This approach used tuntap driver for Linux/Unices
2022-11-16 18:26:49 +01:00
jfsimon1981 d958ec2ac8 Revert "mip_test.c http fetch (#1851)" (#1864)
This reverts commit 07aac8e6e9.
2022-11-16 18:02:23 +01:00
jfsimon1981andJean-Francois Simon 07aac8e6e9 mip_test.c http fetch (#1851)
* Update mip_test.c

* Adding mip_free() function.

* Adding mip_free() function.

* Added MIP free.

* Fixed C++ builds.

* Proper C/C++ struct initialization.

* Squashed commit of the following:

commit 7ba68dd20d
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Wed Nov 16 16:19:50 2022 +0100

    Proper C/C++ struct initialization.

commit aeab3ef7ac
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 17:09:29 2022 +0100

    Fixed C++ builds.

commit 2afd529107
Merge: 14710b81 f8445a4c
Author: jfsimon1981 <jfsimon1981@gmail.com>
Date:   Tue Nov 15 11:33:56 2022 +0100

    Merge branch 'cesanta:master' into master

commit 14710b81e4
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 11:07:15 2022 +0100

    Added MIP free.

commit 6393cd149d
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 11:06:44 2022 +0100

    Adding mip_free() function.

commit feee81b733
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 11:05:55 2022 +0100

    Adding mip_free() function.

commit f8445a4c85
Merge: a39b7ddb 71f5be01
Author: Sergio R. Caprile <scaprile@users.noreply.github.com>
Date:   Fri Nov 11 20:42:38 2022 -0300

    Merge pull request #1853 from cesanta/tibaremetaltest

    Update test.yml

commit 71f5be011b
Author: Sergio R. Caprile <scaprile@users.noreply.github.com>
Date:   Fri Nov 11 20:15:01 2022 -0300

    Update test.yml

commit b53d3cf032
Merge: 7a71038a a39b7ddb
Author: jfsimon1981 <jfsimon1981@gmail.com>
Date:   Fri Nov 11 16:10:53 2022 +0100

    Merge branch 'cesanta:master' into master

commit 7a71038a27
Author: jfsimon1981 <jfsimon1981@gmail.com>
Date:   Fri Nov 11 16:09:22 2022 +0100

    Update mip_test.c

commit a39b7ddbac
Author: cpq <valenok@gmail.com>
Date:   Fri Nov 11 15:03:48 2022 +0000

    Fix fuzzer use-after-poison READ 1

* Squashed commit of the following:

commit 192ae56ece
Merge: 7b0509c8 7ba68dd2
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Wed Nov 16 17:44:03 2022 +0100

    Merge branch 'master' of https://github.com/jfsimon1981/mongoose

commit 7b0509c878
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Wed Nov 16 17:43:33 2022 +0100

    Squashed commit of the following:

    commit 7ba68dd20d
    Author: Jean-Francois Simon <jfsimon@startmail.com>
    Date:   Wed Nov 16 16:19:50 2022 +0100

        Proper C/C++ struct initialization.

    commit aeab3ef7ac
    Author: Jean-Francois Simon <jfsimon@startmail.com>
    Date:   Tue Nov 15 17:09:29 2022 +0100

        Fixed C++ builds.

    commit 2afd529107
    Merge: 14710b81 f8445a4c
    Author: jfsimon1981 <jfsimon1981@gmail.com>
    Date:   Tue Nov 15 11:33:56 2022 +0100

        Merge branch 'cesanta:master' into master

    commit 14710b81e4
    Author: Jean-Francois Simon <jfsimon@startmail.com>
    Date:   Tue Nov 15 11:07:15 2022 +0100

        Added MIP free.

    commit 6393cd149d
    Author: Jean-Francois Simon <jfsimon@startmail.com>
    Date:   Tue Nov 15 11:06:44 2022 +0100

        Adding mip_free() function.

    commit feee81b733
    Author: Jean-Francois Simon <jfsimon@startmail.com>
    Date:   Tue Nov 15 11:05:55 2022 +0100

        Adding mip_free() function.

    commit f8445a4c85
    Merge: a39b7ddb 71f5be01
    Author: Sergio R. Caprile <scaprile@users.noreply.github.com>
    Date:   Fri Nov 11 20:42:38 2022 -0300

        Merge pull request #1853 from cesanta/tibaremetaltest

        Update test.yml

    commit 71f5be011b
    Author: Sergio R. Caprile <scaprile@users.noreply.github.com>
    Date:   Fri Nov 11 20:15:01 2022 -0300

        Update test.yml

    commit b53d3cf032
    Merge: 7a71038a a39b7ddb
    Author: jfsimon1981 <jfsimon1981@gmail.com>
    Date:   Fri Nov 11 16:10:53 2022 +0100

        Merge branch 'cesanta:master' into master

    commit 7a71038a27
    Author: jfsimon1981 <jfsimon1981@gmail.com>
    Date:   Fri Nov 11 16:09:22 2022 +0100

        Update mip_test.c

    commit a39b7ddbac
    Author: cpq <valenok@gmail.com>
    Date:   Fri Nov 11 15:03:48 2022 +0000

        Fix fuzzer use-after-poison READ 1

commit 7ba68dd20d
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Wed Nov 16 16:19:50 2022 +0100

    Proper C/C++ struct initialization.

commit aeab3ef7ac
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 17:09:29 2022 +0100

    Fixed C++ builds.

commit 2afd529107
Merge: 14710b81 f8445a4c
Author: jfsimon1981 <jfsimon1981@gmail.com>
Date:   Tue Nov 15 11:33:56 2022 +0100

    Merge branch 'cesanta:master' into master

commit 14710b81e4
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 11:07:15 2022 +0100

    Added MIP free.

commit 6393cd149d
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 11:06:44 2022 +0100

    Adding mip_free() function.

commit feee81b733
Author: Jean-Francois Simon <jfsimon@startmail.com>
Date:   Tue Nov 15 11:05:55 2022 +0100

    Adding mip_free() function.

commit f8445a4c85
Merge: a39b7ddb 71f5be01
Author: Sergio R. Caprile <scaprile@users.noreply.github.com>
Date:   Fri Nov 11 20:42:38 2022 -0300

    Merge pull request #1853 from cesanta/tibaremetaltest

    Update test.yml

commit 71f5be011b
Author: Sergio R. Caprile <scaprile@users.noreply.github.com>
Date:   Fri Nov 11 20:15:01 2022 -0300

    Update test.yml

commit b53d3cf032
Merge: 7a71038a a39b7ddb
Author: jfsimon1981 <jfsimon1981@gmail.com>
Date:   Fri Nov 11 16:10:53 2022 +0100

    Merge branch 'cesanta:master' into master

commit a39b7ddbac
Author: cpq <valenok@gmail.com>
Date:   Fri Nov 11 15:03:48 2022 +0000

    Fix fuzzer use-after-poison READ 1

Co-authored-by: Jean-Francois Simon <jfsimon@startmail.com>
2022-11-16 17:55:27 +01:00
Sergio R. Caprile 9a341c9032 change MIP MAC to LAA 2022-11-15 14:56:51 -03:00
Sergio R. Caprile 21e8b08ed9 Reduce Zephyr test time 2022-11-14 18:06:00 -03:00
Sergio R. Caprile c41d477adc Update issue_template.md 2022-11-14 14:58:36 -03:00
Sergio R. Caprile f8445a4c85 Merge pull request #1853 from cesanta/tibaremetaltest
Update test.yml
2022-11-11 20:42:38 -03:00
Sergio R. Caprile 71f5be011b Update test.yml 2022-11-11 20:15:01 -03:00
cpq a39b7ddbac Fix fuzzer use-after-poison READ 1 2022-11-11 15:03:48 +00:00
Sergio R. Caprile cab5c822c5 Merge pull request #1850 from cesanta/miplocal
Fix incorrect local network address detection
2022-11-11 11:58:29 -03:00
Sergey Lyubka 4056bd3c2d Merge pull request #1847 from cesanta/xiao
Fix arduino-xiao build and add GA test
2022-11-11 14:53:40 +00:00
Sergio R. Caprile a985ae9c0a Fix incorrect local network address detection 2022-11-11 11:18:47 -03:00
cpq 804a3bf380 Fix #1801 - report ipv4 accepted address for ipv4 listeners 2022-11-11 14:01:17 +00:00
Sergey Lyubka a8bef96463 Merge pull request #1844 from cesanta/tm4c129x
Add TM4C129x driver
2022-11-11 13:15:35 +00:00
Sergey Lyubka 5e43a3f695 Merge pull request #1846 from cesanta/ektm4c129x
Add EK-TM4C1294XL example
2022-11-11 13:15:20 +00:00
cpq 8e46e05e1b Fix arduino-xiao build and add GA test 2022-11-11 10:04:47 +00:00
Sergio R. Caprile ec0e27dbb4 Add EK-TM4C1294XL example 2022-11-10 21:14:30 -03:00
Sergio R. Caprile 3f55d93b41 Merge pull request #1845 from cesanta/mip-tap
Unbreak
2022-11-10 15:01:10 -03:00
Sergio R. Caprile 5418a8c28a Unbreak
userdata was changed to a pointer to a socket, but tx() was not updated

My Linux system does not like mongoose.h at the end...
2022-11-10 15:00:43 -03:00
Sergio R. Caprile e180192379 Add TM4C129x driver 2022-11-10 14:41:41 -03:00
cpq f498d69b7d Fix examples/stm32/nucleo-f429zi-freertos-mip 2022-11-10 03:01:10 +00:00
Sergio R. Caprile dfae1b3f70 Merge pull request #1843 from cesanta/mip
Expose mip guts
2022-11-09 17:40:46 -03:00
Sergio R. Caprile a9ebb55f95 Merge pull request #1842 from cesanta/ft
Add nucleo-f429zi-freertos-mip example
2022-11-09 16:28:33 -03:00
cpq abfac8aa40 Expose mip guts 2022-11-09 19:25:40 +00:00
cpq 78956ccf83 Add nucleo-f429zi-freertos-mip example 2022-11-09 18:25:11 +00:00
Sergey Lyubka eed25f23f6 Merge pull request #1839 from cesanta/stm32uart
Fix wrong reference to prescaler
2022-11-09 09:24:24 +00:00
Sergey Lyubka 134ce56f80 Merge pull request #1841 from cesanta/small
Endianness test
2022-11-09 09:23:04 +00:00
cpq 28a4778187 Endianness test 2022-11-09 09:20:15 +00:00
Sergio R. Caprile c654c2e5e8 Fix wrong reference to prescaler 2022-11-08 11:23:10 -03:00
Sergey Lyubka e580d4e637 Merge pull request #1837 from cesanta/arch
Create MG_ARCH_FREERTOS, MG_ENABLE_LWIP, MG_ENABLE_FREERTOS_TCP. Remo…
2022-11-08 00:13:28 +00:00
cpq 2192914cbb Create MG_ARCH_FREERTOS, MG_ENABLE_LWIP, MG_ENABLE_FREERTOS_TCP. Remove MG_ARCH_FREERTOS_TCP, MG_ARCH_RTX_LWIP 2022-11-07 23:58:58 +00:00
Sergio R. Caprile ca6dee1777 Merge pull request #1836 from cesanta/dewarning
Remove some warnings
2022-11-07 15:29:33 -03:00
Sergio R. Caprile 6f3bdc5dca Remove some warnings 2022-11-07 15:23:47 -03:00
Sergey Lyubka 095cdcd69e Merge pull request #1834 from cesanta/sock
Generalize socket constants
2022-11-05 13:11:57 +00:00
cpq f022633f29 Generalize socket constants 2022-11-05 12:33:49 +00:00
Sergey Lyubka 1f85fcc9b0 Merge pull request #1831 from cesanta/mqtt
Accept zero-length payload messages
2022-11-03 16:46:56 +00:00
Sergio R. Caprile a3ede75842 Accept zero-length payload messages 2022-11-03 11:26:08 -03:00
cpq 0defce37f0 Pull mongoose_custom.h 2022-11-03 12:59:55 +00:00
Sergey Lyubka 4355b39b1e Merge pull request #1830 from cesanta/mip
ARP lookup hosts in the same net. Use up-to-date code in zephyr dash …
2022-11-03 12:35:17 +00:00
cpq efec738c89 ARP lookup hosts in the same net. Use up-to-date code in zephyr dash example 2022-11-03 08:06:17 +00:00
Sergey Lyubka 10c09a361b Merge pull request #1829 from cesanta/cr
CR incorrectly set in STM32 driver
2022-11-02 23:18:20 +00:00
Sergio R. Caprile e3d1a69223 CR incorrectly set in STM32 driver 2022-11-02 19:25:05 -03:00
Sergey Lyubka 4b82253ae9 Merge pull request #1826 from cesanta/custom
mongoose_custom.h not pulled in when MG_ARCH=MG_ARCH_CUSTOM
2022-11-02 12:05:59 +00:00
Sergio R. Caprile 47a12c30ca mongoose_custom.h not pulled in when MG_ARCH=MG_ARCH_CUSTOM 2022-11-01 21:01:33 -03:00
cpq 613655767b Housekeeping at the end of c->label 2022-11-01 21:01:03 +00:00
Sergey Lyubka 1182027f1c Merge pull request #1823 from cesanta/ti-rtos
Fix TI-RTOS port
2022-10-30 09:41:48 +00:00
Sergio R. Caprile e9421d557a Fix TI-RTOS port
Sockets were not being put in non-blocking mode as the setsockopt() call wasn't using SOL_SOCKET
Do not include errno.h but serrno.h, otherwise error codes are mangled... NDK functions use serrno, errno belongs to the compiler
UDP sockets require binding to receive responses
select() does not return write-ready on connect if the amount of bytes to write is below the "low-water mark". This parameter defaults to 2048, there was some code apparently setting this otherwise, with no success. Reworked the code to set this water mark at half the buffer size by just using plain getsockopt/setsockopt calls.

For the record:
	TI typedef's void * SOCKET for internal use, INVALID_SOCKET is cast to (void *). Their BSD compatible socket interface expects and returns int; while Mongoose uses SOCKET... this generates lots of warnings 169 and 515, disabled in the examples
2022-10-28 18:55:10 -03:00
cpq bbc0c0df94 Unbreak test 2022-10-28 15:35:40 +01:00
Sergio R. Caprile 610e32714c Merge pull request #1822 from cesanta/hello
Add mg_hello()
2022-10-28 09:48:43 -03:00
cpq 7ab81d3805 Add mg_hello() 2022-10-28 10:57:06 +01:00
Sergey Lyubka 9a1e41e1fa Merge pull request #1821 from cesanta/docs
Augment WS documentation
2022-10-27 23:09:47 +01:00
Sergio R. Caprile ae71d12f06 Augment WS documentation 2022-10-27 12:03:16 -03:00
cpq c25234df83 Better MIP description 2022-10-27 08:12:22 +01:00
Sergey Lyubka 03284ba046 Merge pull request #1810 from cesanta/zephyresp
Support Zephyr on ESP32
2022-10-25 17:22:47 +01:00
Sergey Lyubka 5fa433ecca Merge pull request #1814 from cesanta/ti-rtos
Improve TI-RTOS timing support
2022-10-25 17:07:33 +01:00
Sergio R. Caprile ac2a4c700a Merge pull request #1818 from cesanta/ti
Allow flash and cloning without build
2022-10-25 10:55:46 -03:00
Sergio R. Caprile eeb7b00f60 Allow flash and cloning without build 2022-10-25 10:41:53 -03:00
Sergio R. Caprile c8c540b453 Improve TI-RTOS timing support 2022-10-24 11:48:54 -03:00
Sergio R. Caprile a0585f75f7 Support Zephyr on ESP32 2022-10-21 11:44:09 -03:00
Sergey Lyubka 637af1d392 Merge pull request #1809 from cesanta/picow
Make pico-w device-dashboard example fully functional
2022-10-20 18:24:38 +01:00
Sergio R. Caprile fe6c31acc1 Make pico-w device-dashboard example fully functional 2022-10-20 11:57:00 -03:00
Sergio R. Caprile 04cfcf751e Merge pull request #1805 from cesanta/invsock
Fix unintended socket close on systems with valid fd=0 descriptor numbering
2022-10-20 11:04:03 -03:00
Sergio R. Caprile 51c51d49ad Fix unintended socket close on systems with valid fd=0 descriptor numbering 2022-10-20 10:34:26 -03:00
cpq 4271aa5b1f Update matrix example name 2022-10-19 09:24:19 +01:00
cpq 17ada1c894 Fix #1803 - conditional for SSL_set1_host(). In unit test, disable time.windows.com, use google and apple SNTP servers 2022-10-19 09:06:47 +01:00
cpq 2e14d125ba Fuzzer nits 2022-10-18 15:21:59 +01:00
cpq ce8fa4c24b Echo WS CLOSE payload back 2022-10-18 14:31:47 +01:00
Sergey Lyubka cfe2e83e6b Merge pull request #1798 from Yeicor/patch-1
Remove mg_hexdump from deliver_chunked_chunks
2022-10-17 07:14:24 +01:00
Yeicor b17c62618d Remove mg_hexdump from deliver_chunked_chunks 2022-10-16 21:11:00 +02:00
Sergey Lyubka 6b162a1193 Merge pull request #1796 from cesanta/rpicow
Dettach git clone and fix clean
2022-10-16 16:59:19 +01:00
Sergey Lyubka 6653530b63 Merge pull request #1797 from strager/fix-typo
Fix typo in documentation
2022-10-16 16:58:20 +01:00
cpq aacae6444e Fix stack overflow in fuzzer - too big on-stack array 2022-10-15 17:18:31 +01:00
Matthew "strager" Glazar b91fe12258 Fix typo in documentation 2022-10-14 18:27:06 -07:00
Sergio R. Caprile ae7ca00e69 Dettach git clone and fix clean
The user has to clone the repo, then edit the Makefile to change WiFi credentials. Running make build does both and the tests go flawlessly
The user can run make to clone the repo, then change credentials and run make build, it will skip cloning if the repo is already there

In some systems the compiled files are not owned by the user as Docker runs as root, so we first invoke clean in the cloned repo (which erases the compiled files), and then remove the cloned repo that the user owns and can rm.
2022-10-14 12:09:39 -03:00
Sergio R. Caprile 0103f1f080 Merge pull request #1795 from cesanta/z
Use board nucleo_f429zi
2022-10-14 08:54:20 -03:00
cpq e8d29d54d6 Use board nucleo_f429zi 2022-10-14 11:39:00 +01:00
Sergey Lyubka 092f2ce0b3 Merge pull request #1794 from cesanta/addMissingTests
Update test.yml
2022-10-11 07:37:53 +01:00
Sergio R. Caprile d89233276b Update test.yml 2022-10-10 17:16:42 -03:00
Sergio R. Caprile 7d797187e8 Merge pull request #1793 from cesanta/device-dashboard
fix paths in Makefile (like other examples)
2022-10-10 17:01:43 -03:00
Sergio R. Caprile 6edcc72364 fix paths in Makefile 2022-10-10 16:51:07 -03:00
Sergey Lyubka 250dfc1377 Merge pull request #1790 from cesanta/zephyr-device-dashboard
Add device-dashboard example on Zephyr
2022-10-10 15:59:08 +01:00
Sergey Lyubka 45489c1c87 Merge pull request #1789 from zudwalex/picow
Add Pico-W example
2022-10-10 15:58:53 +01:00
Sergey Lyubka 09b250f189 Merge pull request #1787 from cesanta/zephyr
Update Zephyr examples
2022-10-10 15:58:39 +01:00
cpq a84465ddba Use MG_SOCK_LISTEN_BACKLOG_SIZE -> 128 for FreeRTOS-TCP 2022-10-10 13:41:07 +01:00
Sergey Lyubka 3b95671442 Merge pull request #1791 from zahar517/fix-json-rpc-example
Fix json-rpc-over-ws example
2022-10-10 10:35:29 +01:00
zahar517 52e66077a7 Fix json-rpc-over-ws example 2022-10-08 14:39:01 +03:00
Sergio R. Caprile 84bf4d21a3 Add device-dashboard example on Zephyr 2022-10-07 11:52:31 -03:00
Alex Alashkin 04cfc510d0 Add Pico-W example 2022-10-07 09:11:35 +03:00
Sergio R. Caprile d846e67ec1 Update Zephyr examples 2022-10-06 17:30:27 -03:00
Sergio R. Caprile 9c60a1bc10 Merge pull request #1788 from cesanta/mod-tests4zephyr
Update test.yml
2022-10-06 17:11:30 -03:00
Sergio R. Caprile f06ac52a43 Update test.yml 2022-10-06 16:55:13 -03:00
Sergio R. Caprile 9e5fd43a2d Update test.yml 2022-10-06 16:46:26 -03:00
Sergio R. Caprile 8d50e7dc82 Update test.yml 2022-10-06 16:32:33 -03:00
cpq 1e6b7bd2a6 Fix broken link 2022-10-05 11:49:06 +01:00
Sergey Lyubka 8346be7a81 Merge pull request #1783 from cesanta/zephyr
Update to latest Zephyr and their Docker repo
2022-10-05 11:41:55 +01:00
Sergey Lyubka 9dc5683fc2 Merge pull request #1785 from cesanta/device-dashboard
rename time() to ourtime()
2022-10-05 11:40:08 +01:00
Sergio R. Caprile e7cb82175a rename time() to ourtime() 2022-10-04 19:27:38 -03:00
Sergio R. Caprile 1ef0aa14c0 Update to latest Zephyr and their Docker repo 2022-10-04 17:24:13 -03:00
cpq 0b3f6d6aab Use CC for fuzzer, not CXX 2022-09-30 11:44:50 +01:00
Sergey Lyubka 0beef1d770 Merge pull request #1781 from jameshilliard/update-spdx
Update GPL license identifier
2022-09-29 20:29:07 +01:00
James Hilliard b944db30fd Update GPL license identifier
GPL-2.0 was deprecated in favor of GPL-2.0-only.

GPL-2.0+ was deprecated in favor of GPL-2.0-or-later.

See: https://spdx.org/licenses/
2022-09-29 15:18:10 -04:00
cpq 6cf3a3feaf Fix fuzzer 2022-09-29 19:31:52 +01:00
cpq 9680b8ccb3 Fix overflow in rx_icmp 2022-09-29 16:53:11 +01:00
cpq a88a11c243 Fix TX overflow in rx_icmp() 2022-09-29 11:13:40 +01:00
Sergey Lyubka 7ff76f69a1 Merge pull request #1777 from jameshilliard/disable-big-endian
Disable broken 32 bit tests and enable 32 bit little endian tests.
2022-09-29 07:33:15 +01:00
James Hilliard c2e4e6d221 Disable broken 32 bit tests and enable 32 bit little endian tests.
It appears there's a bunch of endian specific failing 32 bit tests.
2022-09-28 22:18:08 -06:00
Sergey Lyubka 60edc456a9 Merge pull request #1774 from cesanta/smtp-client
Fix wrong ca.pem path +
2022-09-28 21:58:20 +01:00
Sergey Lyubka 625f804130 Merge pull request #1776 from jameshilliard/32-bit-bigendian
Also test on 32 bit big endian ppc
2022-09-28 21:56:37 +01:00
Sergey Lyubka 7100aaedec Merge pull request #1775 from cesanta/endian
Fix endianness issues in unit test
2022-09-28 21:55:46 +01:00
James Hilliard c867dbc7b2 Also test on 32 bit big endian ppc 2022-09-28 16:02:32 -04:00
cpq 88097f1829 Fix endianness issues in unit test 2022-09-28 20:22:09 +01:00
Sergio R. Caprile 7cf4834336 Fix wrong ca.pem path
Remove extra EHLO before AUTH (there were two)
2022-09-28 16:05:29 -03:00
Sergey Lyubka b5355307a3 Merge pull request #1767 from jameshilliard/bigendian-tests
Test on big endian CPU architectures
2022-09-28 08:08:38 +01:00
James Hilliard 76f693e5d7 Test on big endian CPU architectures 2022-09-26 05:16:49 -04:00
Sergey Lyubka fb3b0ca6e3 Merge pull request #1765 from jameshilliard/rpc-add-calloc-null
Fix null pointer dereference in mg_rpc_add()
2022-09-25 23:22:57 +01:00
James Hilliard 3c71977e2e Fix null pointer dereference in mg_rpc_add()
Fixes #1736
2022-09-25 14:08:58 -04:00
cpq 5574a2663a Close connection on 3 keep-alive misses 2022-09-25 17:35:14 +01:00
cpq 41960b4212 Optimize fuzzer 2022-09-25 11:58:28 +01:00
Sergey Lyubka 6a500b8d40 Merge pull request #1764 from cesanta/fuzz
Optimize fuzzer
2022-09-25 10:31:21 +01:00
Sergey Lyubka dcede59379 Merge pull request #1743 from cesanta/stm32-nucleo-f746z
Stm32 nucleo f746z
2022-09-25 10:22:52 +01:00
Sergey Lyubka 695153c527 Merge pull request #1762 from gdawg/ssdp-example-fix-dupe-responses
Fix SSDP example for second and subsequent responses
2022-09-25 10:20:55 +01:00
cpq c409cca20e Optimize fuzzer 2022-09-25 10:19:17 +01:00
Sergey Lyubka a5a9204f83 Merge pull request #1754 from cesanta/iobuf_init
issue #1734, avoid passing null ptr to memmove
2022-09-24 07:18:42 +01:00
Andrew Griffiths 25d42ad345 Fix SSDP example for second and subsequent responses 2022-09-24 14:14:26 +10:00
Sergio R. Caprile f70a407611 issue #1734, avoid passing null ptr to memmove 2022-09-23 19:34:36 -03:00
Sergio R. Caprile 89f2e66c80 Merge pull request #1752 from cesanta/asan
Activate asan for mip_test
2022-09-23 09:45:18 -03:00
Sergio R. Caprile 4562be52d4 Merge pull request #1753 from cesanta/mg_vprintf
Get rid of va_copy
2022-09-23 09:30:09 -03:00
cpq ebd931f7af Get rid of va_copy 2022-09-23 08:59:02 +01:00
cpq 6a47ff6422 Activate asan for mip_test 2022-09-23 08:35:59 +01:00
cpq 1237185bb4 MIP: atomic -> volatile. Add lease time 2022-09-22 17:16:52 +01:00
Sergio R. Caprile d7fe819699 Merge pull request #1751 from cesanta/stm32-nucleo-f746zg
Add new example as per the tutorial
2022-09-22 12:00:15 -03:00
Sergio R. Caprile 770ffd1483 Add new example as per the tutorial 2022-09-22 11:32:52 -03:00
Sergio R. Caprile 9373e77636 Update Makefile as per the tutorial, enhance it 2022-09-22 11:01:40 -03:00
cpq cb5034548d Fix oob read in rx_dhcp() 2022-09-22 13:42:17 +01:00
Sergey Lyubka f9ad870ff0 Merge pull request #1750 from cesanta/make
Optimize makefile
2022-09-22 13:26:57 +01:00
cpq b538bc3871 Optimize makefile 2022-09-22 12:55:45 +01:00
Sergey Lyubka e5b0528aca Merge pull request #1742 from cesanta/mip-fuzz
Fuzzing MIP
2022-09-21 21:15:50 +01:00
cpq a12bd2271e Fuzzing MIP 2022-09-21 20:29:49 +01:00
Sergey Lyubka 15c5858732 Merge pull request #1746 from cesanta/dtoa
Fix issue #1733
2022-09-21 17:48:06 +01:00
Sergio R. Caprile dd4227f444 Fix issue #1733 2022-09-21 11:38:39 -03:00
Sergey Lyubka fe8a7d8db9 Merge pull request #1748 from cesanta/va_end
Fix issue #1735
2022-09-21 09:43:47 +01:00
Sergey Lyubka ec79ca71b2 Merge pull request #1747 from cesanta/timer_add
Fix issue #1737
2022-09-21 07:16:27 +01:00
Sergio R. Caprile 7a1544e76a Fix issue #1735 2022-09-20 14:26:06 -03:00
Sergio R. Caprile 27ffc23664 Fix issue #1737 2022-09-20 13:54:17 -03:00
Sergio R. Caprile 8ef8ee91e9 Merge pull request #1745 from cesanta/tls-hs
Update README.md with TLS_HS event
2022-09-20 10:53:27 -03:00
Sergio R. Caprile 571625f0c3 Update README.md 2022-09-20 10:52:45 -03:00
Sergio R. Caprile fc2d6eb6bb Merge pull request #1744 from cesanta/smtp
Add smtp client example
2022-09-20 10:38:16 -03:00
cpq 48800504be Add smtp client example 2022-09-20 11:34:22 +01:00
Sergey Lyubka f94a019733 Merge pull request #1741 from cesanta/tls
Fix mbedtls MG_IO_WAIT case
2022-09-19 14:06:31 +01:00
cpq 535d8b9e02 Fix mbedtls MG_IO_WAIT case 2022-09-19 13:38:59 +01:00
Sergey Lyubka 161d44ee04 Merge pull request #1730 from cesanta/stm32-nucleo-f429z
Update Makefile as per the tutorial
2022-09-13 21:46:41 +01:00
Sergey Lyubka 7ea155b943 Merge pull request #1729 from cesanta/mip-tap
Add example to use TAP interface on Linux
2022-09-13 21:46:06 +01:00
Sergio R. Caprile 30acef2452 Merge pull request #1727 from cesanta/mdc
Pass MDC clock divider explicitly rather than guess
2022-09-12 20:43:00 -03:00
cpq 82b50fd3a5 Pass MDC clock divider explicitly rather than guess 2022-09-12 23:57:04 +01:00
Sergio R. Caprile 9e5503dd04 Update Makefile as per the tutorial 2022-09-12 17:29:47 -03:00
Sergio R. Caprile 2ec2ed62c8 Add example to use TAP interface on Linux 2022-09-12 10:52:23 -03:00
cpq 274c11c3ec Update README 2022-09-11 13:42:59 +01:00
cpq 76c4bb556f Update README 2022-09-11 11:23:58 +01:00
cpq 40f484cc54 Update README 2022-09-11 11:20:53 +01:00
cpq 85b701b8c2 Formatting 2022-09-10 21:49:20 +01:00
Sergey Lyubka 7e875ba89d Merge pull request #1726 from cesanta/qp
Add MAC addr filtering to stm32 driver. Record free space in q profiler
2022-09-10 18:19:36 +01:00
cpq c718d7999f Add MAC addr filtering to stm32 driver. Record free space in q profiler 2022-09-10 16:38:03 +01:00
Sergey Lyubka d1472992da Merge pull request #1725 from cesanta/qprofile
Add irq and drop counters to qprofiler
2022-09-09 20:19:19 +01:00
Sergio R. Caprile 995f90aa49 Add irq and drop counters to qprofiler 2022-09-09 14:47:46 -03:00
Sergio R. Caprile a4c27618b4 Update README.md 2022-09-09 14:10:48 -03:00
Sergio R. Caprile 05019529f1 Merge pull request #1724 from cesanta/mgread
Pass long *bytes_read to MG_EV_READ
2022-09-09 14:09:50 -03:00
Sergio R. Caprile 1b5ab3261c Merge pull request #1722 from cesanta/mip-tls
Add mbedtls support to MIP
2022-09-09 14:09:19 -03:00
Sergey Lyubka 6033555ac0 Merge pull request #1723 from cesanta/pcap
Added Linux howto
2022-09-09 17:43:53 +01:00
cpq fd4e1975a3 Pass long *bytes_read to MG_EV_READ 2022-09-09 17:09:18 +01:00
cpq 124ac12150 Add mbedtls support to MIP 2022-09-09 15:53:42 +01:00
Sergio R. Caprile 8c1ffa3f5d Added Linux howto 2022-09-09 10:42:46 -03:00
cpq f76a7e36e8 Corrected MacOS setup diagram 2022-09-08 12:11:01 +01:00
cpq 6484c4bc8b Updated description 2022-09-08 12:09:30 +01:00
cpq bba2421ba9 Corrected MacOS setup diagram 2022-09-08 11:36:01 +01:00
cpq 3c69c7feaf Add MacOS setup diagram 2022-09-08 11:28:16 +01:00
cpq 45b2ffe1af Use DMG_HTTP_DIRLIST_TIME 2022-09-08 11:02:32 +01:00
cpq a57c0f4700 Fix #1712 - JSON parsing for keys with arrays 2022-09-08 10:59:23 +01:00
Sergey Lyubka c33116166f Merge pull request #1720 from cesanta/qprofile
Add rudimentary queue profiler
2022-09-08 10:37:01 +01:00
Sergey Lyubka 50a2063e45 Merge pull request #1713 from behnejad/master
display file modify date in "%Y/%m/%d %H:%M:%S".
2022-09-08 08:55:22 +01:00
cpq cd30cf2d6c Fix #1710 - free MIP in mg_mgr_free() 2022-09-08 08:53:54 +01:00
cpq 419126652e Merge branch 'master' of github.com:cesanta/mongoose 2022-09-08 08:50:51 +01:00
cpq 06ab83dca6 Implement keep-alive, 45 sec interval. Correct ACK piggyback 2022-09-08 08:50:42 +01:00
Sergio R. Caprile 313fddf722 Add rudimentary queue profiler
ETH IRQ and mip_poll() can both write to the queue, so if a memcpy() is interrupted we might see some weird records.
2022-09-07 17:14:03 -03:00
Sergey Lyubka f4def36ccb Merge pull request #1717 from cesanta/fixmipq
Fix MIP Q
2022-09-07 20:59:12 +01:00
Sergey Lyubka 4be8f2ba93 Merge pull request #1719 from cesanta/testq
Make mip_test fail with current queue algo
2022-09-07 20:58:29 +01:00
cpq 881b282604 Implement ack timer 2022-09-07 20:48:23 +01:00
Sergio R. Caprile 9675bfe07d Fix MIP Q 2022-09-07 14:59:58 -03:00
Sergio R. Caprile 443351e95a Make mip_test fail with current queue algo 2022-09-07 14:46:36 -03:00
Behnejad d4cd1c61ee fixing defines. 2022-09-07 22:08:50 +04:30
cpq 75892cb523 Add %f to src/fmt.c 2022-09-07 15:09:52 +01:00
Sergey Lyubka 63e0041644 Merge pull request #1715 from davidhozic/feature/1714
Bug Fix #1714
2022-09-07 15:03:51 +01:00
Sergey Lyubka 70e2d8dd4e Merge pull request #1716 from cesanta/pcap
Make mip-pcap work on Mac
2022-09-07 13:36:14 +01:00
cpq b2624f6055 Make mip-pcap work on Mac 2022-09-07 13:36:00 +01:00
David Hozic 0bb8144677 Bug Fix #1714 2022-09-07 13:35:32 +02:00
Behnejad ad50447ec6 display file modify date in "%Y/%m/%d %H:%M:%S".
adding compile time option to display file modification date as "%Y/%m/%d %H:%M:%S" in http directory indexing.
2022-09-07 09:04:15 +04:30
Sergey Lyubka 84de7437c6 Merge pull request #1711 from cesanta/ethrxsz
Fix Ethernet buffer size
2022-09-06 22:29:23 +01:00
Sergio R. Caprile 419dd50255 Fix Ethernet buffer size
1500 bytes is payload size, which is OK for tx. On the rx side, a full 802.1Q-tagged frame size is 1522 bytes, without the 4-byte CRC = 1518 bytes (1514 for non-VLAN-tagged frames).
2022-09-06 16:53:26 -03:00
Sergio R. Caprile 9dea02e578 Merge pull request #1708 from cesanta/ack
Add mip test
2022-09-05 12:11:24 -03:00
cpq 1c181e091e Add mip test 2022-09-05 15:56:03 +01:00
Sergio R. Caprile 32782bab0e Merge pull request #1706 from cesanta/mg_timer_expired
Introduce mg_timer_expired(). Adopt DHCP and link status to use it
2022-09-05 11:45:53 -03:00
cpq 330783cb5a Corrected clean and examples targets 2022-09-05 14:14:50 +01:00
Sergio R. Caprile 504b004e01 Merge pull request #1707 from cesanta/comments
Use single-line comments
2022-09-05 09:05:28 -03:00
cpq edb861da70 docs 2022-09-05 12:29:06 +01:00
cpq 64ad15895f Small nit in minimal HTTP server example 2022-09-05 12:26:43 +01:00
cpq 44b4944334 Use single-line comments 2022-09-03 09:49:41 +01:00
cpq f9272d0959 Introduce mg_timer_expired(). Adopt DHCP and link status to use it 2022-09-03 09:45:19 +01:00
Sergey Lyubka a113e344a1 Merge pull request #1704 from cesanta/acknow
Re-enable sending ACKs until proper mechanism is in place
2022-09-03 07:46:43 +01:00
Sergey Lyubka 2d80f03f01 Merge pull request #1705 from lionsoul2014/master
fix the doc error: htts to https
2022-09-03 07:44:01 +01:00
lion 542fe9f029 fix the doc error: htts to https 2022-09-03 10:51:09 +08:00
Sergio R. Caprile a1992f5910 Re-enable sending ACKs until proper mechanism is in place 2022-09-02 20:48:30 -03:00
Sergey Lyubka 45a057b0c6 Merge pull request #1703 from cesanta/stm32driver
Extend explanation for MDC clock
2022-09-02 20:02:05 +01:00
Sergio R. Caprile 4a1a26e8b7 Extend explanation for MDC clock 2022-09-02 15:03:46 -03:00
Sergey Lyubka db35e6a427 Merge pull request #1702 from cesanta/stm32driver
Add CR setup, set MDC based on HCLK
2022-09-02 18:46:31 +01:00
Sergio R. Caprile 7358ed25a5 Add CR setup, set MDC based on HCLK 2022-09-02 14:02:02 -03:00
cpq 0d385c29a3 More JSON tests 2022-09-02 16:23:39 +01:00
Sergey Lyubka 51076e68c8 Merge pull request #1701 from cesanta/enableFPU
Enable FPU
2022-09-02 15:46:00 +01:00
Sergio R. Caprile 3270f1252b Enable FPU 2022-09-02 11:18:11 -03:00
Sergey Lyubka d8ee105e1e Merge pull request #1699 from cesanta/scb
Fix SCB address for scb struct
2022-09-02 14:09:08 +01:00
cpq 567fccd7ee Refactor W5500 driver, add arduino w5500 example 2022-09-02 12:58:54 +01:00
cpq f7f7319698 Refactor W5500 driver, add arduino w5500 example 2022-09-02 12:58:54 +01:00
Sergio R. Caprile 62a6b61fc9 Fix SCB address for scb struct 2022-09-01 17:14:31 -03:00
Sergey Lyubka 1a87d9fa77 Merge pull request #1698 from oakfire/master
Fix mg_json_get for the array element result not as expected.
2022-09-01 09:14:10 +01:00
oakfire 8131e30002 Fix mg_json_get for the array element result not as expected. 2022-09-01 15:02:17 +08:00
cpq 83c76bdafc Make mongoose_custom.h a local include, for Arduino builds 2022-08-31 18:20:34 +01:00
cpq cf1566e116 Add more comments in json code 2022-08-31 17:59:04 +01:00
Sergey Lyubka 5d2c977029 Merge pull request #1697 from oakfire/master
fix: #1696  mg_json_get() bugs.
2022-08-31 17:55:12 +01:00
cpq 823c0ef5fb Add enc28j60 driver skeleton 2022-08-31 08:54:33 +01:00
cpq aefc588e6e Unbreak win98 build 2022-08-31 08:53:22 +01:00
cpq 1949439d69 Adopt mip changes 2022-08-31 08:44:05 +01:00
cpq c131b8daf1 struct mip_ipcfg -> struct mip_cfg 2022-08-31 08:41:16 +01:00
cpq 8a61969c8f Add struct mip_spi for SPI drivers, and skeleton for enc28j60 driver 2022-08-31 08:35:06 +01:00
Sergey Lyubka 3cf85770c7 Merge pull request #1694 from cesanta/nucleo-f746zg-baremetal
Group clock setup dependencies
2022-08-30 12:25:41 +01:00
Sergey Lyubka 310b339f0d Merge pull request #1691 from cesanta/docs
Moved packed filesystem section out of the docs
2022-08-30 12:24:30 +01:00
Sergey Lyubka 229b7810df Merge pull request #1695 from cesanta/nucleo-f429zi-baremetal
Add baremetal example on Nucleo-F429ZI
2022-08-30 12:24:15 +01:00
oakfire a686beb9a7 fix: #1696 mg_json_get() bugs. 2022-08-30 14:22:58 +08:00
Sergio R. Caprile 42c1bee8ea Add baremetal example on Nucleo-F429ZI 2022-08-29 19:20:20 -03:00
Sergio R. Caprile c289556775 Group clock setup dependencies 2022-08-29 14:36:40 -03:00
Sergio R. Caprile 941d2f2a3e Moved packed filesystem section out of the docs (relevant parts into the tutorial) 2022-08-29 10:43:29 -03:00
273 changed files with 130788 additions and 3643 deletions

No files matched your search

+1
View File
@@ -10,3 +10,4 @@
- Compiler/IDE and SDK: ZZZ version _X.Y_
- Target hardware/board: _?_
- Connectivity chip/module: _?_
- Target RTOS/OS (if applicable): _?_
+109 -80
View File
@@ -1,41 +1,63 @@
name: build
on: [push, pull_request]
env:
IPV6: 0
jobs:
linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
cc: [gcc, clang]
target: [test, test++, valgrind]
cc: [gcc, clang, g++, clang++]
target: [test, mip_test]
# target: [test]
ssl: [MBEDTLS, OPENSSL]
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
env:
IPV6: 0
CC: ${{ matrix.cc }}
SSL: ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v3
- name: Install packages
run: sudo apt-get update ; sudo apt-get install libmbedtls-dev valgrind
- name: test
run: make ${{ matrix.target }}
- name: unamalgamated
run: make unamalgamated
- run: ./test/setup_ga_network.sh
- run: sudo apt-get update ; sudo apt-get install libmbedtls-dev
- run: make ${{ matrix.target }}
s390:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: sudo apt-get update && sudo apt-get install qemu binfmt-support qemu-user-static
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- run: make s390
armhf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: sudo apt-get update && sudo apt-get install qemu binfmt-support qemu-user-static
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- run: make armhf
linux2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: sudo apt-get update ; sudo apt-get install libmbedtls-dev valgrind
- run: make unamalgamated
- run: make valgrind
- run: make mg_prefix
examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: sudo apt-get install libmbedtls-dev libpcap-dev
- run: sudo apt -y install libmbedtls-dev libpcap-dev
- run: make clean examples
- run: make clean test IPV6=0 MG_ENABLE_POLL=1
- run: make clean test MG_ENABLE_POLL=1
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install jq mbedtls openssl
- run: make test++ upload-coverage IPV6=0 ASAN_OPTIONS=
- run: make test SSL=OPENSSL IPV6=0 ASAN_OPTIONS= OPENSSL=`echo /usr/local/Cellar/openssl*/*`
- run: make test upload-coverage SSL=OPENSSL ASAN_OPTIONS= OPENSSL=`echo /usr/local/Cellar/openssl*/*`
- run: make test SSL=MBEDTLS ASAN_OPTIONS= MBEDTLS=`echo /usr/local/Cellar/mbedtls*/*`
#- run: make mip_test ASAN_OPTIONS=
- run: make mg_prefix
windows:
runs-on: ubuntu-latest
@@ -46,83 +68,90 @@ jobs:
- run: make vc22
- run: make mingw
- run: make mingw++
arduino-xiao:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: make arduino-xiao
arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: make arm
riscv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: make riscv
matrix_examples:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
example:
- name: esp32/device-dashboard
path: esp32/device-dashboard
- name: esp8266
path: esp8266
- name: stm32-freertos-tcp
path: stm32/stm32-freertos-tcp
- name: stm32-nucleo-f746z
path: stm32/stm32-nucleo-f746z
- name: stm32-nucleo-f429z
path: stm32/stm32-nucleo-f429z
- name: stm32-nucleo-h743z
path: stm32/stm32-nucleo-h743z
- name: stm32-nucleo-f746zg-baremetal
path: stm32/nucleo-f746zg-baremetal
- name: nxp-mimxrt1020-azurertos
path: nxp/nxp-mimxrt1020-azurertos
- name: nxp-frdmk66f-freertos
path: nxp/nxp-frdmk66f-freertos
- name: nxp-lpcxpresso54s018m-freertos
path: nxp/nxp-lpcxpresso54s018m-freertos
- name: nxp-mimxrt1020-freertos
path: nxp/nxp-mimxrt1020-freertos
- name: nxp-evkbimxrt1050-lwip-freertos
path: nxp/nxp-evkbimxrt1050-lwip-freertos
- name: nxp-evkmimxrt1020-lwip-freertos
path: nxp/nxp-evkmimxrt1020-lwip-freertos
- name: nxp-evkmimxrt1024-lwip-freertos
path: nxp/nxp-evkmimxrt1024-lwip-freertos
- name: nxp-evkmimxrt1060-lwip-freertos
path: nxp/nxp-evkmimxrt1060-lwip-freertos
- name: nxp-evkmimxrt1064-lwip-freertos
path: nxp/nxp-evkmimxrt1064-lwip-freertos
- name: nxp-evkmimxrt1160-cm7-lwip-freertos
path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
- name: nxp-evkmimxrt1170-cm7-lwip-freertos
path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
- name: nxp-frdmk64f-lwip-freertos
path: nxp/nxp-frdmk64f-lwip-freertos
- name: nxp-frdmk66f-lwip-freertos
path: nxp/nxp-frdmk66f-lwip-freertos
- name: nxp-lpcxpresso54018-lwip-freertos
path: nxp/nxp-lpcxpresso54018-lwip-freertos
- name: nxp-lpcxpresso54608-lwip-freertos
path: nxp/nxp-lpcxpresso54608-lwip-freertos
- name: nxp-lpcxpresso54618-lwip-freertos
path: nxp/nxp-lpcxpresso54618-lwip-freertos
- name: nxp-lpcxpresso54628-lwip-freertos
path: nxp/nxp-lpcxpresso54628-lwip-freertos
- name: nxp-twrk65f180m-lwip-freertos
path: nxp/nxp-twrk65f180m-lwip-freertos
- name: nxp-twrkv58f220m-lwip-freertos
path: nxp/nxp-twrkv58f220m-lwip-freertos
- name: infineon-xmc4700_4800-lwip-rtx-rtos
path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
- name: ti
path: ti/ti-ek-tm4c1294xl-http-server
- name: nucleo_f746zg-zephyr-http-client
path: zephyr/http-client
- name: nucleo_f746zg-zephyr-http-server
path: zephyr/http-server
- name: nucleo_f746zg-zephyr-mqtt-aws-client
path: zephyr/mqtt-aws-client
- name: nucleo_f746zg-zephyr-websocket-server
path: zephyr/websocket-server
name: ${{ matrix.example.name }}
- path: esp32/device-dashboard
- path: esp32/uart-bridge
- path: esp8266/http-client-server
- path: stm32/nucleo-h743zi-baremetal
target: test
- path: stm32/stm32-freertos-tcp
- path: stm32/stm32-nucleo-f746z
- path: stm32/stm32-nucleo-f746zg
- path: stm32/stm32-nucleo-f429z
- path: stm32/stm32-nucleo-h743z
- path: stm32/nucleo-f429zi-baremetal
target: test
- path: stm32/nucleo-f429zi-freertos-mip
- path: stm32/nucleo-f429zi-usb-rndis
- path: stm32/nucleo-f746zg-baremetal
- path: stm32/nucleo-f746zg-freertos-mip
- path: stm32/nucleo-f746zg-usb-rndis
- path: nxp/nxp-mimxrt1020-azurertos
- path: nxp/nxp-frdmk66f-freertos
- path: nxp/nxp-lpcxpresso54s018m-freertos
- path: nxp/nxp-mimxrt1020-freertos
- path: nxp/nxp-evkbimxrt1050-lwip-freertos
- path: nxp/nxp-evkmimxrt1020-lwip-freertos
- path: nxp/nxp-evkmimxrt1024-lwip-freertos
- path: nxp/nxp-evkmimxrt1060-lwip-freertos
- path: nxp/nxp-evkmimxrt1064-lwip-freertos
- path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
- path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
- path: nxp/nxp-frdmk64f-lwip-freertos
- path: nxp/nxp-frdmk66f-lwip-freertos
- path: nxp/nxp-lpcxpresso54018-lwip-freertos
- path: nxp/nxp-lpcxpresso54608-lwip-freertos
- path: nxp/nxp-lpcxpresso54618-lwip-freertos
- path: nxp/nxp-lpcxpresso54628-lwip-freertos
- path: nxp/nxp-twrk65f180m-lwip-freertos
- path: nxp/nxp-twrkv58f220m-lwip-freertos
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
- path: ti/ti-ek-tm4c1294xl-http-server
- path: ti/ek-tm4c1294xl-baremetal
- path: ti/ek-tm4c1294xl-freertos-mip
- path: rp2040/pico-rmii
- path: rp2040/pico-rndis-dashboard
- path: rp2040/pico-w
- path: rp2040/pico-w5500
target: test
name: ${{ matrix.example.path }}
steps:
- uses: actions/checkout@v3
- name: ${{ matrix.example.name }}
run: make -C examples/${{ matrix.example.path }} build
- run: sudo apt -y install gcc-arm-none-eabi
- name: ${{ matrix.example.path }}
run: make -C examples/${{ matrix.example.path }} ${{ matrix.example.target || 'build' }} VCON_API_KEY=${{secrets.VCON_API_KEY}}
zephyr_examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: make -C examples/zephyr init
- name: minify manifest
uses: mikefarah/yq@master
with:
cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' examples/zephyr/zephyrproject/zephyr/west.yml
- run: make -C examples/zephyr update
- run: make -C examples/zephyr/device-dashboard build
- run: make -C examples/zephyr/http-client build
- run: make -C examples/zephyr/http-server build
- run: make -C examples/zephyr/mqtt-aws-client build
- run: make -C examples/zephyr/websocket-server build
+1 -1
View File
@@ -1,5 +1,5 @@
Copyright (c) 2004-2013 Sergey Lyubka
Copyright (c) 2013-2021 Cesanta Software Limited
Copyright (c) 2013-2023 Cesanta Software Limited
All rights reserved
This software is dual-licensed: you can redistribute it and/or modify
+71 -49
View File
@@ -1,40 +1,58 @@
SRCS = mongoose.c test/unit_test.c test/packed_fs.c
HDRS = $(wildcard src/*.h) $(wildcard mip/*.h)
DEFS ?= -DMG_MAX_HTTP_HEADERS=7 -DMG_ENABLE_LINES -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_SSI=1
C_WARN ?= -Wmissing-prototypes -Wstrict-prototypes
WARN ?= -pedantic -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion -Wundef $(C_WARN)
WARN ?= -pedantic -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion -Wundef
OPTS ?= -O3 -g3
VALGRIND_OPTS ?= -O0 -g3
INCS ?= -Isrc -I.
SSL ?= MBEDTLS
SSL ?=
CWD ?= $(realpath $(CURDIR))
ENV ?= -e Tmp=. -e WINEDEBUG=-all
DOCKER ?= docker run --platform linux/amd64 --rm $(ENV) -v $(CWD):$(CWD) -w $(CWD)
VCFLAGS = /nologo /W3 /O2 /MD /I. $(DEFS) $(TFLAGS)
IPV6 ?= 1
ASAN ?= -fsanitize=address,undefined -fno-sanitize-recover=all
ASAN ?= -fsanitize=address,undefined,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
ASAN_OPTIONS ?= detect_leaks=1
EXAMPLES := $(dir $(wildcard examples/*/Makefile)) examples/stm32/nucleo-f746zg-baremetal
EXAMPLES := $(dir $(wildcard examples/*/Makefile))
PREFIX ?= /usr/local
VERSION ?= $(shell cut -d'"' -f2 src/version.h)
COMMON_CFLAGS ?= $(WARN) $(INCS) $(DEFS) -DMG_ENABLE_IPV6=$(IPV6) $(TFLAGS)
COMMON_CFLAGS ?= $(C_WARN) $(WARN) $(INCS) $(DEFS) -DMG_ENABLE_IPV6=$(IPV6) $(TFLAGS)
CFLAGS ?= $(OPTS) $(ASAN) $(COMMON_CFLAGS)
VALGRIND_CFLAGS ?= $(VALGRIND_OPTS) $(COMMON_CFLAGS)
VALGRIND_CFLAGS ?= $(OPTS) $(COMMON_CFLAGS)
VALGRIND_RUN ?= valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --show-leak-kinds=all --leak-resolution=high --track-origins=yes --error-exitcode=1 --exit-on-first-error=yes
.PHONY: examples test valgrind
.PHONY: examples test valgrind mip_test
ifeq "$(findstring ++,$(CC))" ""
# $(CC) does not end with ++, i.e. we're using C. Apply C flags
C_WARN ?= -Wmissing-prototypes -Wstrict-prototypes
else
# $(CC) ends with ++, i.e. we're using C++. Apply C++ flags
C_WARN ?= -Wno-deprecated
endif
ifeq "$(SSL)" "MBEDTLS"
MBEDTLS ?= /usr/local
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
endif
ifeq "$(SSL)" "OPENSSL"
OPENSSL ?= /usr/local
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
endif
all: mg_prefix unamalgamated unpacked test test++ arm examples vc98 vc17 vc22 mingw mingw++ linux linux++ fuzz
all:
$(MAKE) -C examples/http-server
tall: mg_prefix unamalgamated test mip_test arm examples vc98 vc17 vc22 mingw mingw++ fuzz
mip_test: test/mip_test.c mongoose.c mongoose.h Makefile mip_tap_test
$(CC) test/mip_test.c $(INCS) $(WARN) $(OPTS) $(C_WARN) $(ASAN) -o $@
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
mip_tap_test: test/mip_tap_test.c mongoose.c mongoose.h Makefile
$(CC) test/mip_tap_test.c $(INCS) $(WARN) $(OPTS) $(C_WARN) $(ASAN) -o $@
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
examples:
@for X in $(EXAMPLES); do test -f $$X/Makefile || continue; $(MAKE) -C $$X example || exit 1; done
@@ -43,8 +61,8 @@ test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt
$(CC) $(CFLAGS) test/pack.c -o pack
$(RUN) ./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt > $@
DIR ?= test/data/
OUT ?= fs_packed.c
DIR ?= test/data
OUT ?= packed_fs.c
mkfs:
$(CC) $(CFLAGS) test/pack.c -o pack
$(RUN) ./pack -s $(DIR) `find $(DIR) -type f` > $(OUT)
@@ -52,12 +70,7 @@ mkfs:
# Check that all external (exported) symbols have "mg_" prefix
mg_prefix: mongoose.c mongoose.h
$(CC) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T' | grep -v 'mg_' ; test $$? = 1
# C++ build
test++: test
test++: CC = g++
test++: C_WARN = -std=c++2a -Wno-vla -Wno-shadow -Wno-missing-field-initializers -Wno-deprecated
$(CC) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T ' | grep -v 'mg_' ; test $$? = 1
musl: test
musl: ASAN =
@@ -69,20 +82,18 @@ musl: RUN = $(DOCKER) mdashnet/cc1
unamalgamated: $(HDRS) Makefile test/packed_fs.c
$(CC) src/*.c test/packed_fs.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
unpacked:
$(CC) -I. mongoose.c test/unit_test.c -o $@
fuzzer: mongoose.c mongoose.h Makefile test/fuzz.c
clang++ mongoose.c test/fuzz.c $(WARN) $(INCS) $(TFLAGS) -DMG_ENABLE_LINES -fsanitize=fuzzer,signed-integer-overflow,address -Wno-deprecated -Wno-vla-extension -o $@
fuzz: fuzzer
fuzz: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined
fuzz: mongoose.c mongoose.h Makefile test/fuzz.c
$(CC) test/fuzz.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer
$(RUN) ./fuzzer
unit_test: Makefile mongoose.h $(SRCS)
$(CC) $(SRCS) $(CFLAGS) $(LDFLAGS) -g -o unit_test
FUZZDATA ?= /tmp/fuzzdata
fuzz2: mongoose.c mongoose.h Makefile test/fuzz.c
$(CC) test/fuzz.c -DMAIN $(OPTS) $(WARN) $(ASAN) $(INCS) -o fuzzer
$(RUN) ./fuzzer $(FUZZDATA)
# make CC=/usr/local/opt/llvm\@8/bin/clang ASAN_OPTIONS=detect_leaks=1
test: unit_test
test: Makefile mongoose.h $(SRCS)
$(CC) $(SRCS) $(CFLAGS) $(LDFLAGS) -o unit_test
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./unit_test
coverage: CFLAGS += -coverage
@@ -93,14 +104,21 @@ coverage: test
upload-coverage: coverage
curl -s https://codecov.io/bash | /bin/bash
valgrind_unit_test: Makefile mongoose.h $(SRCS)
$(CC) $(SRCS) $(VALGRIND_CFLAGS) $(LDFLAGS) -g -o valgrind_unit_test
valgrind: Makefile mongoose.h mongoose.c
$(CC) $(SRCS) $(VALGRIND_CFLAGS) $(LDFLAGS) -g -o unit_test
$(VALGRIND_RUN) ./unit_test
valgrind: valgrind_unit_test
$(VALGRIND_RUN) ./valgrind_unit_test
armhf: ASAN=
armhf: IPV6=0
armhf: CC = $(DOCKER) mdashnet/armhf cc
armhf: RUN = $(DOCKER) mdashnet/armhf
armhf: test
infer:
infer run -- cc test/unit_test.c -c -W -Wall -Werror -Isrc -I. -O2 -DMG_ENABLE_MBEDTLS=1 -DMG_ENABLE_LINES -I/usr/local/Cellar/mbedtls/2.23.0/include -DMG_ENABLE_IPV6=1 -g -o /dev/null
s390: ASAN=
s390: IPV6=0
s390: CC = $(DOCKER) mdashnet/s390 cc
s390: RUN = $(DOCKER) mdashnet/s390
s390: test
arm: DEFS += -DMG_ENABLE_FILE=0 -DMG_ENABLE_MIP=1 -DMG_ARCH=MG_ARCH_NEWLIB
arm: mongoose.h $(SRCS)
@@ -114,12 +132,10 @@ vc98: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
$(DOCKER) mdashnet/vc98 wine $@.exe
# vc17: DEFS += -DMG_ENABLE_IPV6=1
vc17: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
$(DOCKER) mdashnet/vc17 wine64 $@.exe
# vc22: DEFS += -DMG_ENABLE_IPV6=$(IPV6)
vc22: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
$(DOCKER) mdashnet/vc22 wine64 $@.exe
@@ -128,18 +144,24 @@ mingw: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o $@.exe
$(DOCKER) mdashnet/mingw wine64 $@.exe
arduino: ENV = -v $(CWD)/arduino:/root
arduino:
curl -sL http://downloads.arduino.cc/arduino-1.8.19-linux64.tar.xz | unxz | tar -xf -
mv arduino-* $@
$(DOCKER) mdashnet/cc2 ./arduino/arduino --pref "boardsmanager.additional.urls=https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json" --save-prefs
$(DOCKER) mdashnet/cc2 ./arduino/arduino --pref "compiler.warning_level=all" --save-prefs
$(DOCKER) mdashnet/cc2 ./arduino/arduino --install-boards Seeeduino:samd
arduino-xiao: ENV = -v $(CWD)/arduino:/root
arduino-xiao: arduino
rm -rf tmp; mkdir tmp
cp examples/arduino/w5500/w5500.ino tmp/tmp.ino
cp mongoose.c mongoose.h examples/arduino/w5500/mongoose_custom.h tmp/
$(DOCKER) mdashnet/cc2 ./arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 tmp/tmp.ino
mingw++: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o $@.exe
linux: IPV6=0
linux: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/cc2 gcc $(SRCS) $(CFLAGS) $(LDFLAGS) -o unit_test_gcc
$(DOCKER) mdashnet/cc2 ./unit_test_gcc
linux++: CC = g++
linux++: WARN += -Wno-missing-field-initializers
linux++: linux
linux-libs: CFLAGS += -fPIC
linux-libs: mongoose.o
$(CC) mongoose.o $(LDFLAGS) -shared -o libmongoose.so.$(VERSION)
@@ -157,8 +179,8 @@ mongoose.c: Makefile $(wildcard src/*) $(wildcard mip/*.c)
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c mip/*.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
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/config.h src/str.h src/fmt.h src/log.h src/timer.h src/fs.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/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h mip/mip.h | sed -e 's,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_*.h src/config.h src/str.h src/fmt.h src/log.h src/timer.h src/fs.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/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h mip/mip.h mip/driver_*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
clean:
rm -rf $(PROG) *.exe *.o *.dSYM unit_test* valgrind_unit_test* ut fuzzer *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb slow-unit* _CL_* infer-out data.txt crash-* test/packed_fs.c pack unpacked
@for X in $(EXAMPLES); do $(MAKE) -C $$X clean; done
rm -rf $(PROG) *.exe *.o *.dSYM *_test* ut fuzzer *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb slow-unit* _CL_* infer-out data.txt crash-* test/packed_fs.c pack arduino tmp
find examples -maxdepth 3 -name zephyr -prune -o -name Makefile -print | xargs dirname | xargs -n1 make clean -C
+5
View File
@@ -21,6 +21,11 @@ robust, and easy. Features include:
- 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
- Optional built-in TCP/IP stack with drivers for bare metal or RTOS firmwares
- A full device dashboard
[bare metal example on Nucleo-F429ZI](examples/stm32/nucleo-f429zi-baremetal)
is only 6 files
- For comparison, a CubeIDE generated HTTP example is 400+ files
- Detailed [documentation](https://mongoose.ws/documentation/) and
[tutorials](https://mongoose.ws/tutorials/)
+153 -169
View File
@@ -42,7 +42,7 @@ into the source code tree
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve local dir
if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(c, ev_data, &opts);
if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(c, (struct mg_http_message *)ev_data, &opts);
}
...
@@ -138,7 +138,8 @@ enum {
MG_EV_RESOLVE, // Host name is resolved NULL
MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL
MG_EV_READ, // Data received from socket struct mg_str *
MG_EV_TLS_HS, // TLS handshake succeeded NULL
MG_EV_READ, // Data received from socket long *bytes_read
MG_EV_WRITE, // Data written to socket long *bytes_written
MG_EV_CLOSE, // Connection closed NULL
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
@@ -192,6 +193,28 @@ struct mg_connection {
## Best practices
- Debug log. To increase debug verbosity, call `mg_log_set()`:
```c
mg_log_set(MG_LL_DEBUG);
mg_mgr_init(&mgr);
```
The `MG_INFO()`, `MG_DEBUG()` logging macros use `putchar()` by default,
i.e. they use standard C `stdout` stream. That works fine on the traditional
OS. In the embedded environment, in order to see debug output, two ways
are possible: IO retargeting or Mongoose log redirection. IO retargeting
can already be implemented by an embedded SDK - for example ESP32 SDK
redirects `printf()` to the UART0. Otherwise, IO retargeting can be
implemented manually, see
[guide](https://github.com/cpq/bare-metal-programming-guide#redirect-printf-to-uart)
for more details.
The alternative way is to redirect Mongoose logs:
```c
void log_fn(char ch, void *param) {
output_a_single_character_to_UART(ch);
}
...
mg_log_set_fn(log_fn, param); // Use our custom log function
```
- If you need to perform any sort of initialisation of your connection,
do it by catching `MG_EV_OPEN` event. That event is sent immediately
after a connection has been allocated and added to the event manager,
@@ -255,6 +278,18 @@ struct mg_connection {
By default, IO buffer allocation size `MG_IO_SIZE` is 2048: change it to 512
to trim run-time per-connection memory consumption.
## Architecture diagram
In the Operating System environment, Mongoose uses BSD sockets API provided
by the OS's TCP/IP stack:
![](images/arch2.svg)
In the embedded bare metal environment, Mongoose can utilise its own built-in
stack with network drivers - i.e. it can run directly on top of the hardware:
![](images/arch1.svg)
## Build options
Mongoose source code ships in two files:
@@ -266,20 +301,22 @@ files to the application's source tree. The `mongoose.c` and `mongoose.h` files
are actually an amalgamation - non-amalgamated sources can be found at
https://github.com/cesanta/mongoose/tree/master/src
Mongoose has two types of build constants (preprocessor definitions) that
affect the build: a target architecture, and tunables. In order to set the
option during build time, use the `-D OPTION` compiler flag:
Mongoose has 3 types of build constants (preprocessor definitions) that affect
the build: a target architecture/OS, target network stack, and tunables. In
order to set the option during build time, use the `-D OPTION` compiler flag:
```sh
$ 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_SSI=0 -D MG_IO_SIZE=8192 # Multiple options
$ cc app.c mongoose.c # Use defaults!
$ cc app.c mongoose.c -D MG_ENABLE_IPV6=1 # Build with IPv6 enabled
$ cc app.c mongoose.c -D MG_ARCH=MG_ARCH_RTX # Set architecture
$ cc app.c mongoose.c -D MG_ENABLE_SSI=0 -D MG_IO_SIZE=8192 # 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.
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 |
| ---- | ----------- |
@@ -287,17 +324,26 @@ The architecture is guessed during the build, so setting it is not usually requi
|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_FREERTOS | All systems with FreeRTOS kernel|
|MG_ARCH_AZURERTOS | Microsoft Azure RTOS |
|MG_ARCH_RTX_LWIP | Keil RTX with LWIP TCP/IP stack |
|MG_ARCH_RTX | Keil RTX with MDK TCP/IP stack |
|MG_ARCH_RTX | Keil RTX |
|MG_ARCH_ZEPHYR | Zephyr RTOS |
|MG_ARCH_TIRTOS | TI RTOS |
|MG_ARCH_RP2040 | RP2040 SDK |
|MG_ARCH_NEWLIB | Bare ARM GCC |
|MG_ARCH_CUSTOM | A custom architecture, discussed in the next section |
The network stack constants are listed below. Note that if a network stack
is not specified, then it is assumed that the target architecture supports
standard BSD socket API.
| Name | Default | Description |
| ---- | -------- | ----------- |
|MG_ENABLE_LWIP | 0 | lwIP network stack |
|MG_ENABLE_FREERTOS_TCP | 0 | Amazon FreeRTOS-Plus-TCP network stack |
|MG_ENABLE_RL | 0 | Keil MDK network stack |
|MG_ENABLE_MIP | 0 | Built-in Mongoose network stack |
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. These are tunables that include/exclude
@@ -333,30 +379,33 @@ accordingly.
## Custom build
A custom build should be used for cases which is not covered by the
A custom build should be used for cases not covered by the
existing architecture options (e.g., an embedded architecture that
uses some proprietary RTOS and network stack). In order to build on such
systems, follow the outline below:
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,
and optionally other structures like `DIR *` depending on the functionality
you have enabled - see previous section. Below is an example:
```c
#include <stdbool.h>
#include <stdarg.h>
#define MG_DIRSEP '/'
#define MG_INT64_FMT "%lld"
```
are relevant to your platform. Mongoose uses `bool` type, `MG_DIRSEP` define,
and optionally other structures like `DIR *` depending on the functionality
you have enabled - see previous section. Below is an example:
```c
#include <stdbool.h>
#include <stdarg.h>
#define MG_DIRSEP '/'
#define MG_INT64_FMT "%lld"
```
You can also add a `MG_ARCH` definition:
```c
#define MG_ARCH MG_ARCH_CUSTOM
```
3. This step is optional, and only required if you intend to use a custom
TCP/IP stack. To do that, you should:
* Disable BSD socket API: in the `mongoose_custom.h`, add
```c
#define MG_ENABLE_SOCKET 0
```
```c
#define MG_ENABLE_SOCKET 0
```
* Add an implementation of several internal API functions, like
`mg_send()`, `mg_mgr_poll()`, etc. For the reference, take
a look at the stub
@@ -376,11 +425,11 @@ This example is a simple HTTP server that serves both static and dynamic content
static void fn(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;
if (mg_http_match_uri(hm, "/api/hello")) {
mg_http_reply(c, 200, "", "%s\n", "hi"); // Serve dynamic content
} else {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve
mg_http_serve_dir(c, ev_data, &opts); // static content
if (mg_http_match_uri(hm, "/api/hello")) { // On /api/hello requests,
mg_http_reply(c, 200, "", "{%Q:%d}\n", "status", 1); // Send dynamic JSON response
} else { // For all other URIs,
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve files
mg_http_serve_dir(c, hm, &opts); // From root_dir
}
}
}
@@ -649,7 +698,7 @@ mg_send(c, "hi", 2); // Append string "hi" to the output buffer
```c
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);
```
Same as `mg_send()`, but formats data using `printf()` semantics. Return
@@ -670,27 +719,6 @@ Usage example:
mg_printf(c, "Hello, %s!", "world"); // Add "Hello, world!" to output buffer
```
### mg\_straddr
```c
char *mg_straddr(struct mg_addr *addr, char *buf, size_t len);
```
Write stringified IP address, associated with given connection to `buf` (maximum size `len`)
Parameters:
- `addr` - A address pointer
- `buf` - A pointer to a buffer that will hold stringified address
- `len` - A buffer size
Return value: `buf` value
Usage example:
```c
char buf[100];
LOG(LL_INFO, ("%s", mg_straddr(&c->peer, buf, sizeof(buf))));
```
### mg\_wrapfd()
@@ -736,28 +764,22 @@ Return value: created socket, or `-1` on error
Usage example: see [examples/multi-threaded](https://github.com/cesanta/mongoose/tree/master/examples/multi-threaded).
### mg\_mgr\_wakeup()
### mg\_hello()
```c
bool mg_mgr_wakeup(struct mg_connection *pipe, const void *buf, size_len len);
void mg_hello(const char *url);
```
Wake up an event manager that sleeps in `mg_mgr_poll()` call. This function
must be called from a separate task/thread. A calling thread can pass
some specific data to the IO thread via `buf`, `len`. The maximum value
of `len` is limited by a maximum UDP datagram size, which is 64KiB. If you need
to send a large data to the Mongoose thread, `malloc()` the data and send
a pointer to it, not the data itself. The receiving event handler can receive
a pointer, send a response, and call `free()`. Parameters:
A convenience function that starts a simple web server on a given listening
URL. This function does not return until a "/quit" request is received. A
server handles the following URIs:
- `/quit` - quit the server, and exit the function
- `/debug` - set debug level, expect `{"level": 3}` as a POST payload
- For all other URIs, `hi` is returned as a response
Parameters:
- `pipe` - a special connection created by the `mg_mkpipe()` call
- `buf` - a data to send to the pipe connection. Use `""` if there is no data
- `len` - a data length
Return value: `true` if data has been sent, `false` otherwise
Usage example: see [examples/multi-threaded](https://github.com/cesanta/mongoose/tree/master/examples/multi-threaded).
- `url` - a listening URL, for example `http://0.0.0.0:8000`
## HTTP
@@ -996,12 +1018,13 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
const struct mg_http_serve_opts *opts);
```
Serve static files according to the given options. Note that in order to
enable SSI, set a `-DMG_ENABLE_SSI=1` build flag.
Serve static files according to the given options. Files can also be gzip compressed, including the directory index. All compressed files must end in `.gz` and there must not exist a file with the same name without the extension, otherwise it will take precedence; see [mg_http_serve_file()](#mg_http_serve_file)
<span class="badge bg-warning">NOTE: </span> In order to enable SSI, you need to set the `-DMG_ENABLE_SSI=1` build flag.
<span class="badge bg-danger">NOTE: </span> Avoid double dots `..` in
the `root_dir`. If you need to
reference an upper-level directory, use absolute path.
reference an upper-level directory, use an absolute path.
Parameters:
- `c` - Connection to use
@@ -1033,7 +1056,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
const char *path, struct mg_http_serve_opts *opts);
```
Serve static file.
Serve a static file. If a file with the filename specified in `path` does not exist, Mongoose tries appending `.gz`; and if such a file exists, it will serve it with a `Content-Encoding: gzip` header
<span class="badge bg-danger">NOTE: </span> `opts->root_dir` settings
is ignored by this function.
@@ -1343,7 +1366,7 @@ Parameters:
Return value: offset to the next chunk, or 0 if there are no more chunks.
Usage example (or see [form upload tutorial](../tutorials/form-uploads/) ):
Usage example (or see [form upload tutorial](../tutorials/file-uploads/) ):
```c
struct mg_http_part part;
@@ -1403,18 +1426,50 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
```
## Websocket
## WebSocket
### struct mg\_ws\_message
```c
struct mg_ws_message {
struct mg_str data; // Websocket message data
uint8_t flags; // Websocket message flags
struct mg_str data; // WebSocket message data
uint8_t flags; // WebSocket message flags
};
```
Structure represents the WebSocket message.
This structure represents the WebSocket message, the `flags` element corresponds to the first byte as described in [RFC 6455 section 5.2](https://www.rfc-editor.org/rfc/rfc6455#section-5.2).
#### WebSocket message type:
To extract the message type from an incoming message, check the four LSBs in the `flags` element of the `struct mg_ws_message`.
Possible WebSocket message types:
```c
#define WEBSOCKET_OP_CONTINUE 0
#define WEBSOCKET_OP_TEXT 1
#define WEBSOCKET_OP_BINARY 2
#define WEBSOCKET_OP_CLOSE 8
#define WEBSOCKET_OP_PING 9
#define WEBSOCKET_OP_PONG 10
```
```c
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_WS_MSG) {
struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
msgtype = wm->flags & 0x0F;
if (msgtype == WEBSOCKET_OP_BINARY) {
// This is a binary data message
} else if (msgtype == WEBSOCKET_OP_TEXT) {
// This is a text data message
}
}
}
```
To send a message, use the proper message type as described in [RFC 6455 section 5.6](https://www.rfc-editor.org/rfc/rfc6455#section-5.6) for data frames. when calling [mg_ws_send()](#mg_ws_send) or [mg_ws_printf()](#mg_ws_printf-mg_ws_vprintf) below
### mg\_ws\_connect()
@@ -1424,7 +1479,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
const char *fmt, ...);
```
Create client Websocket connection.
Create client WebSocket connection.
Note: this function does not connect to peer, it allocates required resources and
starts the connect process. Once peer is really connected, the `MG_EV_CONNECT` event is
@@ -1433,7 +1488,6 @@ Note: this function does not connect to peer, it allocates required resources an
Parameters:
- `mgr` - Event manager to use
- `url` - Specifies remote URL, e.g. `http://google.com`
- `opts` - MQTT options, with client ID, QoS, etc
- `fn` - An event handler function
- `fn_data` - An arbitrary pointer, which will be passed as `fn_data` when an
event handler is called. This pointer is also stored in a connection
@@ -1457,9 +1511,9 @@ void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *,
const char *fmt, ...);
```
Upgrade given HTTP connection to Websocket. The `fmt` is a printf-like
Upgrade given HTTP connection to WebSocket. The `fmt` is a printf-like
format string for the extra HTTP headers returned to the client in a
Websocket handshake. Set `fmt` to `NULL` if no extra headers need to be passed.
WebSocket handshake. Set `fmt` to `NULL` if no extra headers need to be passed.
Parameters:
- `c` - Connection to use
@@ -1486,27 +1540,16 @@ void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len, int op);
```
Send data to websocket peer
Send data to WebSocket peer
Parameters:
- `c` - Connection to use
- `buf` - Data to send
- `len` - Data size
- `op` - Websocket message type
- `op` - WebSocket message type, see [WebSocket message type](#websocket-message-type) above
Return value: sent bytes count
Possible Websocket message type:
```c
#define WEBSOCKET_OP_CONTINUE 0
#define WEBSOCKET_OP_TEXT 1
#define WEBSOCKET_OP_BINARY 2
#define WEBSOCKET_OP_CLOSE 8
#define WEBSOCKET_OP_PING 9
#define WEBSOCKET_OP_PONG 10
```
Usage example:
```c
@@ -1528,16 +1571,11 @@ size_t mg_ws_vprintf(struct mg_connection *, int op, const char *fmt, va_list *)
Same as `mg_ws_send()`, but formats data using `printf()` semantics.
<span class="badge bg-danger">NOTE: </span> See [mg\_ws\_send](#mg_ws_send)
for the list of possible Websocket message types
<span class="badge bg-danger">NOTE: </span> See [mg\_snprintf](#mg_snprintf-mg_vsnprintf)
for the list of supported format specifiers
Parameters:
- `c` - Connection to use
- `op` - Websocket message type
- `fmt` - format string in `printf` semantics
- `op` - WebSocket message type, see [WebSocket message type](#websocket-message-type) above
- `fmt` - format string in `printf` semantics. see [mg\_snprintf](#mg_snprintf-mg_vsnprintf)
for the list of supported format specifiers
Return value: sent bytes count
@@ -2320,7 +2358,7 @@ Usage example:
struct mg_str str1 = mg_str("hello");
struct mg_str str2 = mg_strdup(str1);
//...
free(str2.ptr);
free((void *)str2.ptr);
```
@@ -2561,6 +2599,8 @@ Supported format specifiers:
- `q` - expect `char *`, outputs JSON-escaped string (extension)
- `Q` - expect `char *`, outputs double-quoted JSON-escaped string (extension)
- `H` - expect `int`, `void *`, outputs double-quoted hex string (extension)
- `I` - expect `int` (4 or 6), `void *`, outputs IP address (extension)
- `A` - expect `void *`, outputs hardware address (extension)
- `V` - expect `int`, `void *`, outputs double-quoted base64 string (extension)
- `M` - expect `mg_pfn_t`, calls another print function (extension)
- `g`, `f` - expect `double`
@@ -2589,6 +2629,8 @@ mg_snprintf(buf, sizeof(buf), "%05x", 123); // 00123
mg_snprintf(buf, sizeof(buf), "%%-%3s", "a"); // %- a
mg_snprintf(buf, sizeof(buf), "hi, %Q", "a"); // hi, "a"
mg_snprintf(buf, sizeof(buf), "r: %M, %d", f,1,2,7); // r: 3, 7
mg_snprintf(buf, sizeof(buf), "%I", 4, "abcd"); // 97.98.99.100
mg_snprintf(buf, sizeof(buf), "%A", "abcdef"); // 61:62:63:64:65:66
// Printing sub-function for %M specifier. Grabs two int parameters
size_t f(void (*out)(char, void *), void *ptr, va_list *ap) {
@@ -2705,28 +2747,6 @@ if (mg_aton(mg_str("127.0.0.1"), &addr)) {
}
```
### mg\_ntoa()
```c
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
```
Stringify IP address `ipaddr` into a buffer `buf`, `len`
Parameters:
- `addr` - Address to stringify
- `buf` - Pointer to output buffer
- `len` - Output buffer size
Return value: `buf` value
Usage example:
```c
char buf[100];
mg_ntoa(&c->peer, buf, sizeof(buf));
```
## JSON
Note that Mongoose's printing functions support non-standard format specifiers `%Q` and `%M`,
@@ -3801,7 +3821,7 @@ isn't default port for URL protocol
Usage example:
```c
unsigned short port1 = mg_url_port("htts://myhost.com") // port1 is now 443 (default https port)
unsigned short port1 = mg_url_port("https://myhost.com") // port1 is now 443 (default https port)
unsigned short port2 = mg_url_port("127.0.0.1:567") // port2 is now 567
```
@@ -3941,7 +3961,7 @@ Parameters:
- `0` - Disable logging
- `1` - Log errors only
- `2` - Log errors and info messages
- `3` - Log errors, into and debug messages
- `3` - Log errors, info and debug messages
- `4` - Log everything
Return value: None
@@ -4150,39 +4170,3 @@ Usage example:
```c
mg_file_printf(&mg_fs_fat, "/test.txt", "%s\n", "hi");
```
### Packed filesystem
A packed filesystem allow to "pack" filesystem into a C file which then can
be compiled into the binary, forming a read-only file system.
This makes it possible to serve files on devices with no
filesystem. Even on devices with a filesystem, packing some files like Web UI
can be beneficial to be resilient to filesystem errors.
In order to use packed filesystem do the following:
1. Build **pack** tool from test/pack.c:
```sh
$ cc -o pack pack.c
```
2. Convert list of files into single .c:
```sh
$ ./pack index.html style.css > packed_fs.c
```
3. Build your app with `packed_fs.c`:
```sh
$ cc mongoose.c app.c packed_fs.c -DMG_ENABLE_PACKED_FS=1
```
<img src="images/packed.svg" alt="packed filesystem" />
4. In your application code:
```c
struct mg_http_serve_opts opts = {}; // Initialise empty options
opts.fs = &mg_fs_packed; // Use packed filesystem
opts.root_dir = "/"; // Set root directory
mg_http_serve_dir(c, hm, &opts); // Serve directory
```
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="-5.229 8.358 512.162 263.062" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="512.162" height="263.062" x="-5.229" y="8.358" style="" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAArkAAAFmCAYAAABp3oLTAAAAAXNSR0IArs4c6QAAIABJREFUeF7sXQdYFUcXva9TBQEr9t4ARewFNVbsGhG7wRI1UeyixhLRoGLsXZNYYu8NxQJ2FMGKBcWCSAdp0l79v7PPMe8nqEhRILvfh+B7u7MzZ2Z3ztw5914B8QePAI8AjwCPAI8AjwCPAI8Aj0ARQ0BQxNrDN4dHgEeAR4BHgEeAR4BHgEeAR4B4kssPAh4BHgEeAR4BHgEeAR4BHoEihwBPcotcl/IN4hHgEeAR4BHgEeAR4BHgEeBJLj8GeAR4BHgEeAR4BHgEeAR4BIocAjzJLUJdOmnSpIFxcTGW27fv/F0gEKiLUNP4pvAI8AjwCPAI8AjwCPAIfBECPMn9IrgK9snW1tYX79+/39rYxPh1N4duG4cMGbLewcEhqWDXmq8djwCPAI8AjwCPAI8Aj0DeI8CT3LzH9JuVWL9+/YfPX72s06qVPb18+UoTFR4RbN+23YlxY0Yu6NChQ+I3qxh/Yx4BHgEeAR4BHgEeAR6Br4wAT3K/MuD5eTsrG+ug9Ax1jV/d3EgpV9DVq9fp6pUrFBMVGdisRbMj/fsN2DZoUN8X+VkHvmweAR4BHgEeAR4BHgEegYKAAE9yC0Iv5FEdrKxsglIz1DXmL3AjIgHJpHqUnJREd+/cIW/v8xQVFfHStr6198iRwxY4Ojq+zqPb8sXwCPAI8AjwCPAI8AjwCBQ4BHiSW+C6JOcVsrJu8FiuEtea7jqLRAIRqVVqkojFJJNJSalUkN/Na3ThwlmKjAx7ZtfE7tTg4cPXDOrLW3Zzjjh/JY8AjwCPAI8AjwCPQEFFgCe5BbVnclAvKyubh2lKYZ3ZcxaQQEOkUROJxSKSy+WED4oZG5I8PZXu3r9HFy6cp5BXL17XqV372kjnkfOHDXN6moNb8pfwCPAI8AjwCPAI8AjwCBRIBHiSWyC7JWeVqmdl/SBDLao3a/Y8juASCUmtIRIKhKTRqEmjUZKABGRsbEzv3qXQ06eP6OqVi/Tgwf2whg3rew4Z4Lj8hx9+eJKzu/NX8QjwCPAI8AjwCPAI8AgUHAR4kltw+iLXNalnZX0/Qy2y0iW5GpBcoYg0GhVHdAUCAalUahKLxaQnk1BGeiqFvnlN3hfO0f17dyOq16zuPbj/9+4///zzw1xXiC+AR4BHgEeAR4BHgEeAR+AbIcCT3G8EfH7c9lMkl0hNarWKky/AwqtQKEggIJKIRSQSCUmjVtHz4Gd07rwXBT64H1q5UgUv5+FDfh8/fjxv2c2PzuLL5BHgEeAR4BHgEeARyFcEeJKbr/B+3cKzkitoLblauQKIrlKpJJFI8t6iC9Ir5qy8GAgymYwU8gwKCwuliz4X6Kafb2T5cqWv9e7b181t7tx7X7c1/N14BHgEeAR4BHgEeAR4BHKOAE9yc45dgbvSyso6MF0tqptZriAQCEmtVpJYLOTqrNEISKPRcORXrdaQSoXvxCQSibR/i0QkEhKFhLygS5cvUkDArQjz4qbnBjkNWjxnzozHBa7hfIV4BHgEeAR4BHgEeAR4BDIhwJPcIjQk6llZPZRrJHVmzZrLEVnO8UxNnNUWVlytJldLcrWHhvsO5BbyBcTWhX5XpVJxMgapVEwqlZzevHlDvtev0PWrlyNLlyxxxdGxr9vcuXMfFCHo+KbwCPAI8AjwCPAI8AgUMQR4kluEOrSelfUjhUZce+ZHSC5IrfZHa9EF8dXGGsMwYD9CsGIu/hhHijVEBoZ6XJzdmOgIunzxAt28cSNcX1//yvd9+6xesmTR9SIEId8UHgEeAR4BHgEeAR6BIoIAT3KLSEeiGfWsrB8rNOJaOSO5DAghZ92FBVir19WQQiHXOqgJ1Zx1Nzo6mi6cP093bgfEaTQq/8EDB3j89tuCC0UISr4pPAI8AjwCPAI8AjwChRwBnuQW8g7UrX49K+snCo24ZvZJLq6GZZcd+Fur14XDGrS8IpH4PelVEWmUpNaoSCKRklQsotDQ13TnTgD5eJ9P0NfT83Xo6rBq7arfvYoQpHxTvjICPj4+eqmpqabp6elikUgk0NPTSylfvvy7unXryr9yVfjb8QjwCPAI8AgUcgR4klvIO1C3+nWtrIOUGnGNLyG5SA6hpbpMyqAhlRqaXDERibhoDNDpqtVqEomFJBQKSKlQkFBAJJVKQYkpOSmBrl27QhcvXkxSKxT+ffr0XLt69YojRQhavin5gIC/v7/k8uXLTZ88edLh2bNnjRISEsySkpKMU1JS9BQKhVAgEKgNDQ3lUqk0w8TEJMXS0jKsevXqV6pVq3ZrzJgxvvlQJb5IHgEeAR4BHoEihABPcotQZ9arZ/1UQeLq2SW5ILiC905oILkagYYEpCYVtLhQ7Ko1nFMaky9oBAIuexq9TywhEuJ6LT02MJBR/Ns4juz6+fklJycnXOndo9uWtWvXHi1CEPNNyQME1q5da3vu3LnxT548qR8eHl4xOTm5uE6xiHWHIcXl7HsvFoeInBOSS6VSTbFixaIrVKjwxNra2qdz5857nJz4lNR50C3frIi7d+/WDQ0NbfjmzZsaISEhFeLi4iwSExMN09PTEQEmUU9PL8TY2DiqdOnSTytUqPDa0tLyjYODw5tvVmH+xjwCPAKFBgGe5Baarvp8RRnJRQgxaGoRRQG/ESpMyxkyO55lXSYXjIEjuYjGwJzUtFEa1NAxvA8/pj1H9U+UBqGQZFIJxcW9pUePHpDXmZPvMlKT73Xp1m3L5g3rtn++BfwZRRkBd3f3NidPnpwWGBhok5iYaPm+rSpjY+NQc3PzpyVKlHhXunTpRGNjY5WBgYEIx9u3bw0SEhKMo6KiikdGRprEx8eXUSgUxiC/GI9ly5aNsLa2vjlo0KC5gwcP5iN+FIIBpNFoBK9fvx7i4+Mz/PLlyy38/f2l0PmnpKQQiC3eO5BMoX/x7kK0FxxisViur6+fUKxYsYQqVaqE29raXm7WrNkRR0fHu4Wg2XwVc4jAw4cPpS9evCiRnJxsnJaWJhMIBCI9Pb1UExOTBAcHhyiBAO7R/MEj8BE+wwNTdBAAyVUKJJwlNzck90sRYRMSF3pMIuEc1lQqBSkyUunevTt07uzZjKioiBs9uzls3rbtj91fWj5/fuFGYOfOndW2b9++zM/Pr2lycnIpjUajNjMze1KtWrUXzZo1S6pXr16V+vXrNzQxMZEUK1aMS0qCMYRDLpdzP/Hx8fT8+XO6f/8+PXv27K2fn1/GmzdvDJOSkophzJUtWzasffv224YPH/57q1at4gs3YkWz9iC39+/fn3X27Nlpnp6eJkFBQVy/pqWlcWQW/a6vr096enrcb/Qr3ikIb5iRkcERYJyLv1mcbzMzs0g7Ozu/Ll26bHBxcTlTNJH7b7XqxIkTlrdu3er86NGjjmFhYSVjY2PNEhMTTdLS0vQVCoUEq1uZTKbU09NLNjIyijM3N48uV67cyyZNmpysUaPGw169eoX+txDjW/spBHhLbhEaH9Y29Z8qSVJ9husvpFKxUGFwJIPZ6x/N7T8hxPKm8bC44AcTEou7q4EVmNSkpyejlHfJdOeOP13wvpARGx15r327trsmT3bZYGdnh+C8/FGEEZg2bdqAw4cPz3n+/HltmPwtLCzu29vbB3Tr1q2Kra1tm/Lly5OhoSFHchixhSUPPxhPID7swP9BdGDxA0Hy9fUlLy+v9Js3b2pSUlL0oRG3tbW9MWzYMJexY8f6FWFYC13THj161Mvb23v1vn37yqPv4uLiOKJqampKlpaWVLVqVapSpQr3u0yZMoTFDsguDvR3QkIChYWF0evXr+np06cUHBycERYWpkpJSTHAOSYmJolNmjS57uzs/IuTk9PtQgcQX2Fyd3fv5+PjM/bx48e1oqOjS2ZkZIgwn2Cc4N0hEok0EokEc4ZGoVBIVSoVi3vJoWdgYJBYsmTJ6Dp16jy1t7f/c8aMGYd5WHkEeJJbhMZA/QYNgxQkrjF9+ixSKrHdB6lB/pNcQAjtLiMnDFKRSEhKhZJEYhEZ6EkpJeUdPX70kC6c96LwyDDfFi2bHRg6YMDWnj17JhehbuCbQkQ+Pj7iLVu2/H706NFBqamp5sWKFXtlZ2d3w9nZuXybNm1agNiwA5Y5zomR6WSyQJCNLbagYtvYgYGBdOTIETpw4IAa5EmlUglh1Rk6dKjrb7/9tp/vjG+PwNmzZ5ft3LlzyokTJzjCisWKubk5NWjQgNq0aUOtWrWimjVrcp9ppVUfP7DISUpKoocPH9KFCxfo2rVrbwIDAxWxsbGVcVX58uVfd+3adevgwYNXtmzZkn+vfPvu/2wNXF1dB3l7e4978uSJbVJSkh6ecbFYrDI0NBSUKlVKiHdFiRIlyNjYmIyMjLh5hi18sFiKiIhAWMuMd+/eCZVKpQSk2MTEJLVmzZq3O3fuvPHXX3/dzUsaPtsNRfYEnuQWoa5taNcoSEGSGlOmupJSoX5PPDkJbb5acrXaXW3mNLxg8H8cAkxYXDgyDYmFQhLAUY3wvYIeBj6gs+fO0Juw0KB2rdp4OjkNX9SnT/u4ItQd/9mm+Pj4mC5atGjb1atXu6Snp0urVKlyrWfPnqEDBgxwql27NkdoMVYYoXlvqeHGEJO+ALwP4+j9TgEjwex8kCWUk5iYCFJNhw8fpvPnz8sjIyOlJUqUiHV0dFy0bt26lf/ZjigADd+2bdu+rVu3Ovr7+3N9W7x4cWrRogV1796dmjdvTuXKlfuwwGH9qjsGuPfI+/7XhjbU/qDfU1NTKSQkhLy9veXHjx9/fPPmzdJJSUmlIHNo2rTppfHjx493dHTkddoFYBxkVYWNGzfa7NixY+n9+/ebvHv3zLine truncated
</svg>

After

Width:  |  Height:  |  Size: 163 KiB

+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="-11.551 4.783 524.391 265.184" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="524.391" height="265.184" style="" x="-11.551" y="4.783" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAr4AAAFjCAYAAADbzwgZAAAAAXNSR0IArs4c6QAAIABJREFUeF7sXQdYVEcXvVvYpQqiYsUWuyJgb7E3sJcQo7Fgxd4FrFhjrLF3FHuLDewFRMUGCip2QRQRFaV3dvf/zuDohh8EpAjyJh8fxH1v3syZ2Tdn7px7r4iEIiAgICAgICAgICAgICAgICAgUAAQEBWAPgpdFBAQEBAQEBAQEBAQEBAQEBAQIIH4CpNAQEBAQEBAQEBAQEBAQEBAoEAgIBDfAjHMQicFBAQEBAQEBAQEBAQEBAQEBOIrzAEBAQEBAQEBAQEBAQEBAQGBAoGAQHwLxDALnRQQEBAQEBAQEBAQEBAQEBAQiK8wBwQEBAQEBAQEBAQEBAQEBAQKBAIC8S0Qwyx0UkBAQEBAQEBAQEBAQEBAQEAgvgVgDhw/flxv5syZ66tWrRrcr1+/hT169AgrAN0WuiggICAgICAgICAgICAg8B8EBOJbACaEk5NT6YEDB/pLpVJp0aJFnjRp0vR4nz59lltZWX0oAN0XuiggICAgICAgICAgICAgwBAQiG8BmAhbt24tZ2Nj49utW3ed4sWLk4eHB717F/yscePG5/v06fO3lZXVqwIAg9BFAQEBAQEBAQEBAQGBAo6AQHwLwATYsmVLhWHDhj+bPM1e0qJFGwoJCSHf+z50yfUiBb4JfF7XzPzw4MED1lpZWb0pAHAIXRQQEBAQEBAQEBAQECigCAjEtwAM/I4dO34ZNGjIk/GT7ST1GzalxIRE0tHWpMjISHr69BGdPXuGAl48e1K3bh3n4cMHQwIRXABgEbooICAgICAgICAgICBQwBAQiG8BGPCtW7dWGjp0xGNGfBs1o4T4BFIpFSQRi0lbW5tiYiLp2dPHdOH8OfLze36/Vo0axwYPttnQv3+vtwUAHqGLAgICAgICAgICAgICBQQBgfgWgIF2cnKqMnDg4EfjJ9uJGzRsRgkJiUzdDeKbkJhAEpGItOQyUqiU9ND3AV29cpke+D54WrNmjTOD+vdZMHjwYMEJrgDME6GLAgICAgICAgICAj87AgLx/dlHmIi2b99ezdp66MPxk+1EjPgmJVFSkoJEIhFpSCWkVCpIpVQxJDQ1ZSRSqejJ06d0xf0yPX784H7FCsb7f/+t16YxY8Z8LABwCV0UEBAQEBAQEBAQEBD4SREQiO9POrDq3XJ0dKwxePAw3/GT7ahBo2YUG5dAYomYFAoFScUSUqmSSS+KWESkTEokbR0dUiqV5Of3jK5dcaW7d7weGhuXdu77x++LJ06cKMQBLgDzRuiigICAgICAgICAwM+GgEB8f7YRTaU/27dvN7G2HnZv4lR7qtegKcXGxzNrr3rB/6sUSpJIQISVjPRKxBKSSsQklRAFBLykixfPk7f3XS+jYkWODhrQd9OUKVNCCgB8QhcFBAQEBAQEBAQEBAR+EgQE4vuTDOS3urFli1PtYcOG+HDiG5eQkOrlmAww/v5nUqhUzAoMSYREIqagt0F0/twZuuN167Gevt7FP/v8NtPBwUGwABeAeSR0UUBAQEBAQEBAQCC/IyAQ3/w+ghlo//bt282srYfdTY/48qpEX5UPzDKMH8giJCIiOZzgFEkUHPyGPDyukdvlSz6G+voH/+xr9Y+Dg0NMBpojXCIgICAgICAgICAgICAg8EMQEIjvD4E9dx+6dauT+dChQ+5w4hsfn7rFV71Vqi8zAxIIIpUIxFdMKkggpGKSSsWkIZFQ8LtguuzmRrdv3nygrS073qVT+7+WLVsWnbs9FJ4mICAgICAgICAgICAgIJA+AgLxTR+jfH+Fo6NjncGDh3t9Jb6J6fTpq8lXxbTAKlKSiml+SakkpUr52SlOycivXC6noDdv6NatG3TZ9aynplxy2MLCYsOaNWsi8j14QgcEBAQEBAQEBAQEBAR+GgQE4vvTDGXaHeHEd9JUe6rboCnFx4P4pjX0IL1qxJdUJBKLSCSWkFKhYHcplEoSi0SMCCuTFMwRTltbi90XFRFCV69eVrlfdnuWpEhy69Wj2+xVq1a9KwAwC13MQQRUKpVIJFIX4eTgw4SqBQQEBAQEBAR+WgQE4vvTDu3XjjHiO8TGa8o0ezKv1+gz8c3+jmMySSUiksmkLB3y1SvuSIbxKDY25kgfq+7/LF++XIgCkf2w/zQ1qlQqDQ8Pj5qvXr2q8erVq9oBAQHmERERhWJjY2WJiYkiqVSqKFKkSHThwoUDy5Qpc7dSpUoPS5cufd/U1DTwpwFB6IiAgICAgICAQI4iIBDfHIU3b1SeW8QXvU1WRihZQgwdHS0KDw+lO163ydX10ovYmMgr7dq0W75t28YHeQMZoRV5AYFz587V8/Dw+NPT07P1y5cvSwUGBupHRkZKcZLAC481zcPwyWQyhaGhYXS5cuXCTE1NnzVo0GBno0aNXGrWrPkpL/RJaMP3IfDhwwe9z3OgelRUVOHo6OhCRKTU0dGJ0tPTCylcuPDLEiVKvK1ataqwif4+iIW7BAQKPAIC8S0AUyA3iS9EEkiBDCkEMsKBCMtlUoqOjmIE+NKliwEfQz6e69DJYvMux02eBQB+oYtpIODs7Nz4yJEjM93c3OoHBAQUA7kFsUUsaW1tbdLS0mI/0JBLpVJKSkqi6Ohoio2Npfj4ePaTmJisV9fX14+qXr36406dOu3r1q3bHhMTE0Fekw9mnq+vr+zt27fV7t+/3/7evXttnz17Vubt27eGMTExenFxcZpxcXESSFzkcnmSTCaL19TUjDI0NAyrUKHCm7p167qbmpperV69+p1ffvklPB90V2jidyDg7++vqVQq5UqlUpaUlKSUyWSYCwnGxsax31GdcIuAQJpCTwGanwiBXCW+KjGRCBZfJYnEYpKKYQBWMgKspanJJBDe3nfIze3yu48hwbfbtGq6YdeuXad+IriFrqSDwKVLl6oeOnRoyqlTpzq/fv26BAivjo4OFS5cmKpWrcp+qlevTuXKlQOhJU1NTRKLxZSQkEARERFsDj148ICeP39Ojx8/Jn9/fwoPT+Y9mpqaCSYmJj4DBw78a+TIkUeFwcibCLx48ULf3d29vbOz87gHDx5UDgoKMoqKivqPIQabIJlMxjqAsVfPMIl/09HRURYuXPhjrVq1nrVo0eJI69atjzRs2NA/b/ZYaFVGEbh8+XIFf3//On5+fi3evn1rFhQUZBgVFSWPj4+XiMVilba2dlKhQoXiSpQo8bp06dKe5cuXv161atVH9erVe5XRZwjXFWwEBItvARj/3CS+iUlKFutXJCZSJCYxCx4sdWI4yKmgARaTXFNGUVHR9OD+Xbrkejbs/bt3l5s1buJ46ND+EwVgOApsF2G5OXLkSJ9t27ZNffr0aTWFQiE2MDAgExMTRnR79OjB/jYyMmJW35TZBdWBAwmC9Rfk9/r16+Tu7k5XrlxhpDgqKooKFSoU2rFjxzODBg2a3bFjx+cFFvQ81vHg4GCdf//99zdnZ+fR169frx4eHq6DJsKiX6xYsYjixYtHFStWLL5s2bKKQoUKgdzCq5FiYmKkYWFh0qCgIMnHjx813r17p/n27VvdhIQEtobp6OhEmpmZPWnXrt2+Xr16CRb/PDbu6TXn2rVr5c6fP9//7t27HR8+fFguMDCwWGxsrDy9+zBvihQpEleuXLm31apVu9+oUaNDTZs2dRN0/+khV7A/F4hvARh/xPEdYWNzZ9IUWzKt04ASEpJyrNdiiZSSFElM5sDJC/S+mGhikZhFgED0B2SBQyxgRVIc+T54QBcvXIh+GeB/u3XrlhsO7tt9MMcaKFT8QxDw9fUtsWTJkvXHjx9vFR4ebgD5Qu3atal79+7UsWNHqlatGmloaHxOmZ0cVYQnT0mtwZA4YH7BEoyN1du3b+nJkye0a9cucnV1pTdv3rDPzM3NPW1sbCYOGTLk6g/puPDQLwicOXOmwbZt2xZfunSpwcePHxnhLVSoUJSJiUlE06ZNk8zNzUtWqlRJo2TJkkzqAmsv5gQKxhg/kLl8+PCB/Pz8YPVP8vDwiHzw4IE4ICBAH9dpa2tHt2jR4vaff/65uF+/fmcF+PM2Aq6urpWcnZ0nnTp1ysLf37885Eu86OnpJRQqVChGX18/XldXN0lHR0eB9SMqKkocFhYmiYiIkOFdkpCQIOHvC2yWqlWr9qRbt26OHTt23F2nTp2gvI2A0LofgYBAfH8E6rn8TGRuG24z5u6kybZkYlYvR4kvidkr6P97qFRLB/f502QyrCKxBPGBFfTk8SM6f/Fs7KuX/lcbNai7Z/DgQYe6dOkiZIPL5fmS3Y+7fft2xSVLlmw7ceJESxxZ6+npUf/+/alfv35kZmbGpAwgNbDepCxpWX1TOrtxYgQpxMmTJ2nnzp3MEoznVapU6fmQIUMm2dnZOWd334T6MobAypUrh+/bt2/q7du3K2HsDAwMEhs3bvxx9OjRhapVq6ZtbGzMSC7Gm2u906oZWST5vAgJCaE7d+7QoUOHkk6ePJn47t07xFWkihUr+ltZWW3p37//JsHhMWNjlJtX4fRn/fr105ydnQc+fvy4IieuhoaGH83NzRPMzMxkNWvWLAK5U6lSpdg7Aj8oOOnBqQ42u8+fPw++f/9+hI+Pj9zX19cgMjKSbYAgnTI1NfXp37//Ihsbm8Mikeirp2xudlR4Vp5EQCC+eXJYsrdR27btMrUZZeMNi29ts/o5Fs6MtVr8/wQX/8wWs/98BOuvilnlxBIRiZQq0pRrUFxCHPn7PafzZ08rnj9/+qBuXXPnoYMH/dOzZ8+P2YuKUFtuIHDt2rVf5syZs+fSpUsNMdY1atSg4cOHU6dOnahs2bKfZTBiZr1NrXxL7qB+PSxBLine truncated
</svg>

After

Width:  |  Height:  |  Size: 158 KiB

-384
View File
@@ -1,384 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 858.5 424.3" style="enable-background:new 0 0 858.5 424.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#9E9B83;}
.st1{fill:#9E8900;}
.st2{font-family:Arial;font-weight:bold;}
.st3{font-size:11px;}
.st4{display:none;fill:#576174;}
.st5{fill:#1F5F75;}
.st6{clip-path:url(#SVGID_3_);fill:#FFFFFF;fill-opacity:0.1;}
.st7{fill:#277691;}
.st8{fill:#FFFFFF;}
.st9{font-family:Arial;font-weight:bold;}
.st10{fill:#004219;}
.st11{clip-path:url(#SVGID_6_);fill:#FFFFFF;fill-opacity:0.1;}
.st12{fill:#005721;}
.st13{fill:url(#SVGID_7_);}
.st14{clip-path:url(#XMLID_13_);fill:#FFFFFF;fill-opacity:0.1;}
.st15{fill:#752E06;}
.st16{fill:#963B08;}
.st17{fill:#59008F;}
.st18{clip-path:url(#XMLID_15_);fill:#FFFFFF;fill-opacity:0.1;}
.st19{fill:#7300B8;}
.st20{fill:#FFDE00;}
.st21{fill:#576174;}
.st22{font-size:13px;}
.st23{fill:#8A8C8E;}
.st24{font-size:12px;}
.st25{opacity:0.69;}
.st26{fill:#B3B1B3;}
.st27{clip-path:url(#XMLID_17_);fill:#FFFFFF;fill-opacity:0.1;}
.st28{fill:#919091;}
.st29{fill:#BFBEBF;}
.st30{fill:#454445;}
.st31{font-size:9px;}
.st32{clip-path:url(#XMLID_19_);fill:#FFFFFF;fill-opacity:0.1;}
.st33{fill:#8695B3;}
.st34{fill:url(#SVGID_8_);}
.st35{font-size:18px;}
.st36{clip-path:url(#XMLID_20_);fill:#610041;fill-opacity:0.1;}
.st37{fill:#610041;}
.st38{clip-path:url(#XMLID_22_);fill:url(#SVGID_9_);fill-opacity:0.1;}
.st39{fill:none;stroke:#86005B;stroke-width:0.5;stroke-linecap:round;stroke-miterlimit:10;}
.st40{fill:none;stroke:#86005B;stroke-width:0.75;stroke-linecap:round;stroke-miterlimit:10;}
.st41{fill:url(#SVGID_10_);}
.st42{fill:url(#SVGID_11_);}
.st43{fill:#610042;}
.st44{fill:url(#SVGID_12_);}
</style>
<g>
<g>
<path class="st0" d="M457.9,111.2l0.1,87.3c0,1.4-1.1,2.6-2.5,2.6h-76.3c-4.4-0.2-7.3-3.9-7.3-5.3l4.7-101.8
c0-1.4,0.8-7.4,2.2-7.4l54-0.1L457.9,111.2z"/>
</g>
<g>
<text transform="matrix(1 0 0 1 383.2604 149.9447)" class="st1 st2 st3">packed_fs.c</text>
</g>
</g>
<rect x="84" y="25" class="st4" width="727.7" height="429.8"/>
<g>
<g>
<path class="st5" d="M207.5,104.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V84.5c0-1.4,1.1-2.5,2.5-2.5h58
L207.5,104.6z"/>
<g>
<defs>
<path id="SVGID_1_" d="M205.5,102.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5V82.5c0-1.4,1.1-2.5,2.5-2.5
h58L205.5,102.6z"/>
</defs>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="122.1091" y1="136.2824" x2="205.5191" y2="136.2824">
<stop offset="0" style="stop-color:#45CFFF"/>
<stop offset="1" style="stop-color:#85DDFA"/>
</linearGradient>
<use xlink:href="#SVGID_1_" style="overflow:visible;fill:url(#SVGID_2_);"/>
<clipPath id="SVGID_3_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<path class="st6" d="M121.4,101.4c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V101.4z"/>
</g>
<path class="st5" d="M205.9,104.4l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L205.9,104.4z"/>
<path class="st7" d="M205.7,102.8h-20.5c-1.4,0-2.5-1.1-2.5-2.5V79.9l0,0l22.9,22.7L205.7,102.8z"/>
<g>
<text transform="matrix(1 0 0 1 129.0689 92.8531)" class="st8 st9 st3">filex.y</text>
</g>
</g>
<g>
<path class="st10" d="M191.4,121.6V209c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V101.4c0-1.4,1.1-2.5,2.5-2.5h58
L191.4,121.6z"/>
<g>
<defs>
<path id="SVGID_4_" d="M189.4,119.6V207c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5V99.4c0-1.4,1.1-2.5,2.5-2.5
h58L189.4,119.6z"/>
</defs>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="106.0386" y1="153.2384" x2="189.4486" y2="153.2384">
<stop offset="0" style="stop-color:#00983A"/>
<stop offset="1" style="stop-color:#3A985D"/>
</linearGradient>
<use xlink:href="#SVGID_4_" style="overflow:visible;fill:url(#SVGID_5_);"/>
<clipPath id="SVGID_6_">
<use xlink:href="#SVGID_4_" style="overflow:visible;"/>
</clipPath>
<path class="st11" d="M105.3,118.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V118.3z"/>
</g>
<path class="st10" d="M189.8,121.3l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L189.8,121.3z"/>
<path class="st12" d="M189.6,119.7h-20.5c-1.4,0-2.5-1.1-2.5-2.5V96.9l0,0l22.9,22.7L189.6,119.7z"/>
<g>
<text transform="matrix(1 0 0 1 113.9984 109.809)" class="st8 st9 st3">main.js</text>
</g>
</g>
<g>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="93.2369" y1="173.2516" x2="176.6469" y2="173.2516">
<stop offset="0" style="stop-color:#EA5B0C"/>
<stop offset="1" style="stop-color:#EA671E"/>
</linearGradient>
<path class="st13" d="M176.6,139.6V227c0,1.4-1.1,2.6-2.5,2.6H95.8c-1.4,0-2.5-1.1-2.5-2.6V119.5c0-1.4,1.1-2.5,2.5-2.5h58
L176.6,139.6z"/>
<g>
<defs>
<path id="XMLID_2_" d="M174.6,137.6V225c0,1.4-1.1,2.6-2.5,2.6H93.8c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1c0-1.4,1.1-2.5,2.5-2.5
h58L174.6,137.6z"/>
</defs>
<linearGradient id="XMLID_12_" gradientUnits="userSpaceOnUse" x1="91.2369" y1="171.2516" x2="174.6469" y2="171.2516">
<stop offset="0" style="stop-color:#EA5B0C"/>
<stop offset="1" style="stop-color:#EA7B3D"/>
</linearGradient>
<use xlink:href="#XMLID_2_" style="overflow:visible;fill:url(#XMLID_12_);"/>
<clipPath id="XMLID_13_">
<use xlink:href="#XMLID_2_" style="overflow:visible;"/>
</clipPath>
<path class="st14" d="M90.5,136.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V136.3z"/>
</g>
<path class="st15" d="M175,139.3l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L175,139.3z"/>
<path class="st16" d="M174.8,137.7h-20.5c-1.4,0-2.5-1.1-2.5-2.5v-20.3l0,0l22.9,22.7L174.8,137.7z"/>
<g>
<text transform="matrix(1 0 0 1 97.1967 127.8222)" class="st8 st9 st3">style.css</text>
</g>
</g>
<g>
<path class="st17" d="M164.6,157.7v87.4c0,1.4-1.1,2.6-2.5,2.6H83.8c-1.4,0-2.5-1.1-2.5-2.6V137.5c0-1.4,1.1-2.5,2.5-2.5h58
L164.6,157.7z"/>
<g>
<defs>
<path id="XMLID_1_" d="M162.6,155.7v87.4c0,1.4-1.1,2.6-2.5,2.6H81.8c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1c0-1.4,1.1-2.5,2.5-2.5
h58L162.6,155.7z"/>
</defs>
<linearGradient id="XMLID_14_" gradientUnits="userSpaceOnUse" x1="79.2009" y1="189.3131" x2="162.6108" y2="189.3131">
<stop offset="0" style="stop-color:#A000FF"/>
<stop offset="1" style="stop-color:#C96EFF"/>
</linearGradient>
<use xlink:href="#XMLID_1_" style="overflow:visible;fill:url(#XMLID_14_);"/>
<clipPath id="XMLID_15_">
<use xlink:href="#XMLID_1_" style="overflow:visible;"/>
</clipPath>
<path class="st18" d="M78.5,154.4c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V154.4z"/>
</g>
<path class="st17" d="M163,157.4l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L163,157.4z"/>
<path class="st19" d="M162.8,155.8h-20.5c-1.4,0-2.5-1.1-2.5-2.5V133l0,0l22.9,22.7L162.8,155.8z"/>
<g>
<text transform="matrix(1 0 0 1 83.1607 145.8838)" class="st8 st9 st3">index.html</text>
</g>
</g>
</g>
<g>
<g>
<path class="st20" d="M455.2,108.2v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V88.1c0-1.4,1.1-2.5,2.5-2.5h58
L455.2,108.2z"/>
<path class="st0" d="M455.3,110.3l-18.4,0c-1.4,0-2.5-1.1-2.5-2.5V87.5l0,0l20.9,20.7L455.3,110.3z"/>
<polygon class="st0" points="435.2,109.7 432.9,107.3 436.3,106.9 "/>
<path class="st1" d="M455.4,108.3h-20.5c-1.4,0-2.5-1.1-2.5-2.5V85.5l0,0l22.9,22.7L455.4,108.3z"/>
</g>
<g>
<text transform="matrix(1 0 0 1 379.2604 144.9447)" class="st21 st9 st22">packed_fs.c</text>
</g>
</g>
<g>
<polygon class="st23" points="483.6,195.4 397.3,195.4 394.3,193.4 397.3,162.8 481.5,159.7 483.6,162.8 "/>
<rect x="394.3" y="159.8" class="st21" width="87.3" height="33.7"/>
<g>
<g>
<text transform="matrix(1 0 0 1 400.0845 171.7588)" class="st8 st9 st24">mg_unpack()</text>
</g>
<g>
<text transform="matrix(1 0 0 1 400.0845 186.935)" class="st8 st9 st24">mg_unlist()</text>
</g>
</g>
</g>
<g class="st25">
<g>
<path class="st26" d="M467.7,256.6V344c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V236.4c0-1.4,1.1-2.5,2.5-2.5h58
L467.7,256.6z"/>
<g>
<defs>
<path id="XMLID_9_" d="M465.7,254.6V342c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1c0-1.4,1.1-2.5,2.5-2.5
h58L465.7,254.6z"/>
</defs>
<linearGradient id="XMLID_16_" gradientUnits="userSpaceOnUse" x1="382.3115" y1="288.2073" x2="465.7215" y2="288.2073">
<stop offset="0" style="stop-color:#D6D4D6"/>
<stop offset="1" style="stop-color:#FFFDFE"/>
</linearGradient>
<use xlink:href="#XMLID_9_" style="overflow:visible;fill:url(#XMLID_16_);"/>
<clipPath id="XMLID_17_">
<use xlink:href="#XMLID_9_" style="overflow:visible;"/>
</clipPath>
<path class="st27" d="M381.6,253.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V253.3z"/>
</g>
<path class="st28" d="M466.1,256.3l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L466.1,256.3z"/>
<path class="st29" d="M465.9,254.7h-20.5c-1.4,0-2.5-1.1-2.5-2.5v-20.3l0,0l22.9,22.7L465.9,254.7z"/>
<text transform="matrix(1 0 0 1 386.2713 244.7779)" class="st30 st9 st31">mongoose.c</text>
</g>
<g>
<path class="st26" d="M455.7,276.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V256.5c0-1.4,1.1-2.5,2.5-2.5h58
L455.7,276.6z"/>
<g>
<defs>
<path id="XMLID_8_" d="M453.7,274.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1
c0-1.4,1.1-2.5,2.5-2.5h58L453.7,274.6z"/>
</defs>
<linearGradient id="XMLID_18_" gradientUnits="userSpaceOnUse" x1="370.2755" y1="308.2689" x2="453.6855" y2="308.2689">
<stop offset="0" style="stop-color:#D6D4D6"/>
<stop offset="1" style="stop-color:#FFFDFE"/>
</linearGradient>
<use xlink:href="#XMLID_8_" style="overflow:visible;fill:url(#XMLID_18_);"/>
<clipPath id="XMLID_19_">
<use xlink:href="#XMLID_8_" style="overflow:visible;"/>
</clipPath>
<path class="st32" d="M369.6,273.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V273.3z"/>
<use xlink:href="#XMLID_8_" style="overflow:visible;fill:none;stroke:#FFFDFE;stroke-width:0.25;stroke-miterlimit:10;"/>
</g>
<path class="st28" d="M454,276.4l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L454,276.4z"/>
<path class="st29" d="M453.8,274.8h-20.5c-1.4,0-2.5-1.1-2.5-2.5v-20.3l0,0l22.9,22.7L453.8,274.8z"/>
<text transform="matrix(1 0 0 1 379.2353 264.8395)" class="st30 st9 st31">app.c</text>
</g>
</g>
<g>
<polygon class="st33" points="342.3,123.3 351.1,141.7 342.3,160.7 234.8,160.9 234.8,122.6 "/>
<path class="st23" d="M347.4,145.4"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="233.6667" y1="139.4088" x2="350.0318" y2="139.4088">
<stop offset="0" style="stop-color:#C1D5FF"/>
<stop offset="0.1995" style="stop-color:#BACDF6"/>
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
<stop offset="1" style="stop-color:#ADC0E6"/>
</linearGradient>
<polygon class="st34" points="341.2,120.9 350,139.3 341.2,158.3 233.7,158.5 233.7,120.3 "/>
<text transform="matrix(1 0 0 1 262.9869 146.2633)" class="st8 st9 st35">PACK</text>
<polygon class="st33" points="234.8,160.9 233.7,158.5 238,158.7 "/>
</g>
<g>
<path class="st23" d="M634.9,144.6L634.9,144.6z"/>
</g>
<g>
<polygon class="st33" points="619.6,139.3 619.6,139.3 618.7,137.4 618.7,137.4 "/>
<path class="st23" d="M623.1,168.2L623.1,168.2z"/>
</g>
<g>
<polygon class="st33" points="619.6,288.1 618.7,290 618.7,290 619.6,288.1 "/>
<path class="st23" d="M623.1,259.2L623.1,259.2z"/>
</g>
<g>
<path class="st23" d="M617,282L617,282z"/>
</g>
<g>
<g>
<g>
<defs>
<path id="XMLID_10_" d="M722.7,276.5h-71.2c-11.6,0-21.1-9.4-21.1-21.1v-71.2c0-11.6,9.4-21.1,21.1-21.1h71.2
c11.6,0,21.1,9.4,21.1,21.1v71.2C743.8,267,734.4,276.5,722.7,276.5z"/>
</defs>
<use xlink:href="#XMLID_10_" style="overflow:visible;fill:#610041;"/>
<clipPath id="XMLID_20_">
<use xlink:href="#XMLID_10_" style="overflow:visible;"/>
</clipPath>
<path class="st36" d="M754.3,172.5c-2.7,8-17.3,30.9-65.8,30.8c-24.5,0-48.4-7.4-65.7-24.7l-12.1-12l69.3-64.6L754.3,172.5z"/>
</g>
<polygon class="st37" points="637.6,271.2 632.5,266.1 640.3,269.4 "/>
<polygon class="st37" points="738.3,169.9 734.6,166.2 736.4,171 "/>
<g>
<defs>
<path id="XMLID_5_" d="M719.7,273.5h-71.2c-11.6,0-21.1-9.4-21.1-21.1v-71.2c0-11.6,9.4-21.1,21.1-21.1h71.2
c11.6,0,21.1,9.4,21.1,21.1v71.2C740.8,264,731.4,273.5,719.7,273.5z"/>
</defs>
<radialGradient id="XMLID_21_" cx="684.119" cy="216.7761" r="56.6929" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#8B005D;stop-opacity:0.7"/>
<stop offset="1" style="stop-color:#8B005D"/>
</radialGradient>
<use xlink:href="#XMLID_5_" style="overflow:visible;fill:url(#XMLID_21_);"/>
<clipPath id="XMLID_22_">
<use xlink:href="#XMLID_5_" style="overflow:visible;"/>
</clipPath>
<radialGradient id="SVGID_9_" cx="678.486" cy="148.5836" r="90.2195" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#8B005D"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
</radialGradient>
<path class="st38" d="M750.3,168.5c-2.7,8-17.3,30.9-65.8,30.8c-24.5,0-48.4-7.4-65.7-24.7l-12.1-12L676,97.9L750.3,168.5z"/>
</g>
<g>
<g>
<g>
<g>
<text transform="matrix(1 0 0 1 646.3768 216.49)" class="st8 st9 st35">APP.EXE</text>
</g>
</g>
</g>
</g>
</g>
<g>
<g>
<g>
<path class="st8" d="M732,240.1c-0.3-1.4-0.8-2.7-1.4-3.9l1.7-2.3c-0.3-0.5-0.6-0.9-1-1.4c-0.3-0.5-0.7-0.9-1.1-1.3l-2.7,1
c-1-1-2.2-1.8-3.4-2.4l0-2.9c-1-0.4-2.1-0.8-3.2-1l-1.5,2.4c-1.4-0.2-2.8-0.2-4.1,0l-1.7-2.4c-1.1,0.2-2.1,0.6-3.1,1.1l0.2,2.9
c-0.6,0.3-1.2,0.7-1.7,1.1c-0.6,0.4-1.1,0.9-1.5,1.4l-2.7-0.9l-1.9,2.7l1.8,2.3c-0.6,1.3-1,2.6-1.1,4l-2.7,0.9
c-0.1,1.1,0,2.2,0.1,3.3l2.8,0.8c0.3,1.3,0.8,2.7,1.4,3.9l-1.7,2.3c0.3,0.5,0.6,0.9,1,1.4c0.3,0.4,0.7,0.9,1.1,1.3l2.7-1
c1,1,2.2,1.8,3.4,2.4l0,2.9c1,0.4,2.1,0.8,3.2,1l1.5-2.4c1.4,0.2,2.8,0.2,4.1,0l1.7,2.4c1.1-0.3,2.1-0.6,3.1-1.1l-0.2-2.9
c0.6-0.3,1.2-0.7,1.7-1.1c0.6-0.4,1.1-0.9,1.5-1.4l2.8,0.9c0.7-0.8,1.3-1.8,1.9-2.7L731,249c0.6-1.3,1-2.6,1.1-4l2.7-0.9
c0.1-1.1,0-2.2-0.1-3.3L732,240.1z M724,251c-4.6,3.5-11.1,2.6-14.6-2c-3.5-4.6-2.6-11.1,2-14.6s11.1-2.6,14.6,2
C729.5,241,728.6,247.5,724,251z"/>
</g>
</g>
<g>
<g>
<path class="st8" d="M700.5,249.3c-0.2-0.8-0.5-1.6-0.8-2.4l1-1.4c-0.2-0.3-0.4-0.6-0.6-0.8c-0.2-0.3-0.4-0.5-0.7-0.8l-1.6,0.6
c-0.6-0.6-1.3-1.1-2.1-1.4l0-1.7c-0.6-0.3-1.3-0.5-1.9-0.6l-0.9,1.4c-0.8-0.1-1.7-0.1-2.5,0l-1-1.4c-0.6,0.1-1.3,0.4-1.9,0.6
l0.1,1.7c-0.4,0.2-0.7,0.4-1,0.7c-0.3,0.3-0.6,0.5-0.9,0.8l-1.6-0.6l-1.1,1.6l1.1,1.4c-0.3,0.8-0.6,1.6-0.7,2.4l-1.6,0.5
c0,0.7,0,1.3,0.1,2l1.7,0.5c0.2,0.8,0.4,1.6,0.9,2.4l-1,1.4c0.2,0.3,0.4,0.6,0.6,0.8c0.2,0.3,0.4,0.5,0.7,0.8l1.6-0.6
c0.6,0.6,1.3,1.1,2.1,1.4l0,1.7c0.6,0.3,1.3,0.5,1.9,0.6l0.9-1.4c0.8,0.1,1.7,0.1,2.5,0l1,1.4c0.6-0.2,1.3-0.4,1.9-0.6l-0.1-1.7
c0.4-0.2,0.7-0.4,1-0.7c0.3-0.3,0.6-0.5,0.9-0.8l1.6,0.6c0.4-0.5,0.8-1.1,1.1-1.6l-1.1-1.4c0.3-0.8,0.6-1.6,0.7-2.4l1.6-0.5
c0-0.7,0-1.3-0.1-2L700.5,249.3z M694.5,254.2c-1.8,1.4-4.5,1-5.9-0.8c-1.4-1.8-1-4.5,0.8-5.9c1.8-1.4,4.5-1,5.9,0.8
C696.8,250.2,696.4,252.8,694.5,254.2z"/>
</g>
</g>
<path class="st39" d="M708.9,234.5"/>
<path class="st39" d="M706.7,237.9"/>
<path class="st40" d="M705.7,242.7c0-1.7,0.4-3.4,1-4.9"/>
<path class="st40" d="M708.9,234.5c2.2-2.4,5.3-3.8,8.8-3.8"/>
<path class="st40" d="M687.4,247.3c1.1-1.4,2.7-2.2,4.6-2.2"/>
<path class="st39" d="M686.4,249.5"/>
<path class="st40" d="M686.2,250.9c0-0.5,0.1-1,0.2-1.4"/>
<path class="st39" d="M686.7,253.2"/>
</g>
</g>
<g>
<path class="st33" d="M611.7,174.2l-23,3.3l-13.1-9.6c-6.3-4.6-13.9-7.1-21.7-7l-55.5,0.1l-1.1-2.4h1.1l64.2-0.2h0.1l3.9,0h0.1
l3.2,2.4l19.2,14l0.2,0.2l23.4-3.3L611.7,174.2z"/>
<path class="st23" d="M595.9,145.5L595.9,145.5z"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="497.2089" y1="147.636" x2="612.739" y2="147.636">
<stop offset="0" style="stop-color:#C1D5FF"/>
<stop offset="0.1995" style="stop-color:#BACDF6"/>
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
<stop offset="1" style="stop-color:#ADC0E6"/>
</linearGradient>
<path class="st41" d="M612.7,171.7l-3,0.4l-20.3,2.8l-0.2-0.1l-13.6-9.9l0,0c-3.7-2.7-8.7-4.4-12.9-5.4c-2.9-0.7-6-1-9-1l-35.5,0.1
l-19.8,0.1h-1.1v-38.3l13.5,0.2l4,0l42.6,0.2l7.9,0c7,0,14,1.6,20.2,4.9c0,0,0,0,0,0c0.8,0.5,1.6,0.9,2.4,1.5l7.5,5.6l0.1,0.1l0,0
l15.4,11.3v0l0.1,3.2L612.7,171.7z"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="597.6228" y1="138.4046" x2="598.5728" y2="138.4046">
<stop offset="0" style="stop-color:#C1D5FF"/>
<stop offset="0.1995" style="stop-color:#BACDF6"/>
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
<stop offset="1" style="stop-color:#ADC0E6"/>
</linearGradient>
<polygon class="st42" points="598.6,139.3 598.6,139.4 597.6,137.4 597.7,137.5 "/>
<text transform="matrix(1 0 0 1 513.7678 146.3103)" class="st8 st9 st35">BUILD</text>
</g>
<g>
<path class="st33" d="M612.7,258.8l-0.1,2.2l-1.8-0.2l-20.3-2.8l-0.2,0.1l-13.6,9.9l0-0.1c-3.7,2.7-8.7,4.4-12.9,5.4
c-2.9,0.7-6,1-9,1l-35.5-0.1l-19.8-0.1h-1.1v35.4l-1.1,0.4l1.1,2.4l13.5-0.2l4,0l42.6-0.2l7.9-0.1c7,0,14-1.6,20.2-4.9c0,0,0,0,0,0
c0.8-0.5,1.6-0.9,2.4-1.5l7.5-5.6l0.1-0.1l0,0l15.4-11.3l1-0.9l1.9-26.7L612.7,258.8z"/>
<path class="st43" d="M593.5,272.5"/>
<g>
<path class="st23" d="M598.5,285L598.5,285z"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="497.2089" y1="451.0054" x2="612.739" y2="451.0054" gradientTransform="matrix(1 0 0 -1 0 733.8616)">
<stop offset="0" style="stop-color:#C1D5FF"/>
<stop offset="0.1995" style="stop-color:#BACDF6"/>
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
<stop offset="1" style="stop-color:#ADC0E6"/>
</linearGradient>
<path class="st44" d="M612.7,258.8l-3-0.4l-20.3-2.8l-0.2,0.1l-13.6,9.9l0,0c-3.7,2.7-8.7,4.4-12.9,5.4c-2.9,0.7-6,1-9,1
l-35.5-0.1l-19.8-0.1h-1.1v38.3l13.5-0.2l4,0l42.6-0.2l7.9,0c7,0,14-1.6,20.2-4.9c0,0,0,0,0,0c0.8-0.5,1.6-0.9,2.4-1.5l7.5-5.6
l0.1-0.1l0,0l15.4-11.3v0l0.1-3.2L612.7,258.8z"/>
<text transform="matrix(1 0 0 1 513.7682 298.0848)" class="st8 st9 st35">BUILD</text>
</g>
</g>
<path class="st33" d="M619.9,149.1"/>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

+1
View File
@@ -0,0 +1 @@
../../../mongoose.c
+1
View File
@@ -0,0 +1 @@
../../../mongoose.h
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "Arduino.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#define MG_ARCH MG_ARCH_CUSTOM
#define MG_ENABLE_SOCKET 0
#define MG_ENABLE_MIP 1
#define mkdir(a, b) (-1)
//#define MG_ENABLE_LOG 0
+49
View File
@@ -0,0 +1,49 @@
#include <SPI.h>
#include "mongoose.h"
#define SS_PIN 3 // Slave select pin
struct mg_mgr mgr; // Mongoose event manager
struct mip_spi spi = {
NULL, // SPI data
[](void *) { digitalWrite(SS_PIN, LOW); }, // begin transation
[](void *) { digitalWrite(SS_PIN, HIGH); }, // end transaction
[](void *, uint8_t c) { return SPI.transfer(c); }, // execute transaction
};
struct mip_if mif = {.mac = {2, 0, 1, 2, 3, 5}}; // MIP network interface
void setup() {
Serial.begin(115200);
pinMode(SS_PIN, OUTPUT);
SPI.begin();
// Set logging function to a serial print
mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
mg_mgr_init(&mgr);
delay(3000);
MG_INFO(("Starting TCP/IP stack..."));
mif.driver = &mip_driver_w5500;
mif.driver_data = &spi;
mip_init(&mgr, &mif);
// Start a 5 sec timer, print status message periodically
mg_timer_add(
&mgr, 5000, MG_TIMER_REPEAT,
[](void *) {
MG_INFO(("ethernet: %s", mip_driver_w5500.up(&mif) ? "up" : "down"));
},
NULL);
// Setup HTTP listener. Respond "ok" on any HTTP request
mg_http_listen(
&mgr, "http://0.0.0.0",
[](struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "ok\n");
},
&mgr);
}
void loop() {
mg_mgr_poll(&mgr, 1);
}
+33 -11
View File
@@ -3,15 +3,19 @@
#include "mongoose.h"
#if !defined(MQTT_SERVER)
#define MQTT_SERVER "mqtt://broker.hivemq.com:1883"
#endif
#define MQTT_PUBLISH_TOPIC "mg/my_device"
#define MQTT_SUBSCRIBE_TOPIC "mg/#"
static time_t s_boot_timestamp = 0; // Updated by SNTP
#ifndef DISABLE_ROUTING
static struct mg_connection *s_sntp_conn = NULL; // SNTP connection
#endif
// Define system time()
time_t time(time_t *tp) {
// Define a system time alternative
time_t ourtime(time_t *tp) {
time_t t = s_boot_timestamp + (time_t) (mg_millis() / 1000);
if (tp != NULL) *tp = t;
return t;
@@ -76,7 +80,7 @@ static struct user *getuser(struct mg_http_message *hm) {
static void send_notification(struct mg_mgr *mgr, const char *fmt, ...) {
struct mg_connection *c;
for (c = mgr->conns; c != NULL; c = c->next) {
if (c->label[0] == 'W') {
if (c->data[0] == 'W') {
va_list ap;
va_start(ap, fmt);
mg_ws_vprintf(c, WEBSOCKET_OP_TEXT, fmt, &ap);
@@ -88,10 +92,12 @@ static void send_notification(struct mg_mgr *mgr, const char *fmt, ...) {
// Send simulated metrics data to the dashboard, for chart rendering
static void timer_metrics_fn(void *param) {
send_notification(param, "{%Q:%Q,%Q:[%lu, %d]}", "name", "metrics", "data",
(unsigned long) time(NULL),
(unsigned long) ourtime(NULL),
10 + (int) ((double) rand() * 10 / RAND_MAX));
}
#ifndef DISABLE_ROUTING
// MQTT event handler function
static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
if (ev == MG_EV_CONNECT && mg_url_is_ssl(s_config.url)) {
@@ -103,6 +109,7 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
c->is_hexdumping = 1;
mg_mqtt_sub(s_mqtt, mg_str(s_config.sub), 2);
send_notification(c->mgr, "{%Q:%Q,%Q:null}", "name", "config", "data");
MG_INFO(("MQTT connected, server %s", MQTT_SERVER));
} else if (ev == MG_EV_MQTT_MSG) {
struct mg_mqtt_message *mm = ev_data;
send_notification(c->mgr, "{%Q:%Q,%Q:{%Q: %.*Q, %Q: %.*Q, %Q: %d}}", "name",
@@ -111,7 +118,7 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
"qos", (int) mm->qos);
} else if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
MG_DEBUG(("cmd %d qos %d", mm->cmd, mm->qos));
MG_DEBUG(("%lu cmd %d qos %d", c->id, mm->cmd, mm->qos));
} else if (ev == MG_EV_CLOSE) {
s_mqtt = NULL;
if (s_connected) {
@@ -126,7 +133,8 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
static void timer_mqtt_fn(void *param) {
struct mg_mgr *mgr = (struct mg_mgr *) param;
if (s_mqtt == NULL) {
struct mg_mqtt_opts opts = {0};
struct mg_mqtt_opts opts;
memset(&opts, 0, sizeof(opts));
s_mqtt = mg_mqtt_connect(mgr, s_config.url, &opts, mqtt_fn, NULL);
}
}
@@ -136,7 +144,6 @@ static void timer_mqtt_fn(void *param) {
static void sfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_SNTP_TIME) {
uint64_t t = *(uint64_t *) ev_data;
MG_INFO(("%lu SNTP: %lld ms from epoch", c->id, t));
s_boot_timestamp = (time_t) ((t - mg_millis()) / 1000);
c->is_closing = 1;
} else if (ev == MG_EV_CLOSE) {
@@ -152,13 +159,17 @@ static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time
}
}
#endif
// HTTP request handler function
void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
void *fn_data) {
if (ev == MG_EV_OPEN && c->is_listening) {
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_metrics_fn, c->mgr);
#ifndef DISABLE_ROUTING
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_mqtt_fn, c->mgr);
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_sntp_fn, c->mgr);
#endif
s_config.url = strdup(MQTT_SERVER);
s_config.pub = strdup(MQTT_PUBLISH_TOPIC);
s_config.sub = strdup(MQTT_SUBSCRIBE_TOPIC);
@@ -169,13 +180,22 @@ void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
// u ? u->name : "NULL"));
if (mg_http_match_uri(hm, "/api/hi")) {
mg_http_reply(c, 200, "", "hi\n"); // Testing endpoint
} else if (mg_http_match_uri(hm, "/api/debug")) {
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
mg_log_set(level);
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
} else if (u == NULL && mg_http_match_uri(hm, "/api/#")) {
// All URIs starting with /api/ must be authenticated
mg_http_reply(c, 403, "", "Denied\n");
} else if (mg_http_match_uri(hm, "/api/config/get")) {
#ifdef DISABLE_ROUTING
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q,%Q:%Q}\n", "url", s_config.url,
"pub", s_config.pub, "sub", s_config.sub);
#else
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q,%Q:%Q,%Q:%s}\n", "url",
s_config.url, "pub", s_config.pub, "sub", s_config.sub,
"connected", s_connected ? "true" : "false");
#endif
} else if (mg_http_match_uri(hm, "/api/config/set")) {
// Admins only
if (strcmp(u->name, "admin") == 0) {
@@ -196,13 +216,14 @@ void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
}
mg_http_reply(c, 200, "", "ok\n");
} else if (mg_http_match_uri(hm, "/api/watch")) {
c->label[0] = 'W'; // Mark ourselves as a event listener
c->data[0] = 'W'; // Mark ourselves as a event listener
mg_ws_upgrade(c, hm, NULL);
} else if (mg_http_match_uri(hm, "/api/login")) {
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q}\n", "user", u->name, "token",
u->token);
} else {
struct mg_http_serve_opts opts = {0};
struct mg_http_serve_opts opts;
memset(&opts, 0, sizeof(opts));
#if 1
opts.root_dir = "/web_root";
opts.fs = &mg_fs_packed;
@@ -211,7 +232,8 @@ void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
#endif
mg_http_serve_dir(c, ev_data, &opts);
}
MG_DEBUG(("%.*s %.*s -> %.*s", (int) hm->method.len, hm->method.ptr,
(int) hm->uri.len, hm->uri.ptr, (int) 3, &c->send.buf[9]));
MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len,
hm->method.ptr, (int) hm->uri.len, hm->uri.ptr, (int) 3,
&c->send.buf[9]));
}
}
File diff suppressed because it is too large. Load diff
+14 -7
View File
@@ -1,6 +1,8 @@
'use strict';
import {Component, h, html, render, useEffect, useState, useRef} from './preact.min.js';
var devaddr = "address:port";
const MaxMetricsDataPoints = 50;
// This simple publish/subscribe is used to pass notifications that were
@@ -53,14 +55,14 @@ const Hero = props => html`
using <code>curl</code> command-line utility:
</p>
<div><code>curl -u admin:pass0 localhost:8000/api/config/get</code> </div>
<div><code>curl -u admin:pass0 localhost:8000/api/config/set -d 'pub=mg/topic'</code> </div>
<div><code>curl -u admin:pass0 localhost:8000/api/message/send -d 'message=hello'</code> </div>
<div><code>curl -u admin:pass0 ${devaddr}/api/config/get</code> </div>
<div><code>curl -u admin:pass0 ${devaddr}/api/config/set -d 'pub=mg/topic'</code> </div>
<div><code>curl -u admin:pass0 ${devaddr}/api/message/send -d 'message=hello'</code> </div>
<p>
The device can send notifications to this dashboard at anytime. Notifications
are sent over WebSocket at URI <code>/api/watch</code> as JSON strings: <code>{"name": "..", "data": ...}</code>
<div>Try <code>wscat --auth user1:pass1 --connect ws://localhost:8000/api/watch</code></div>
<div>Try <code>wscat --auth user1:pass1 --connect ws://${devaddr}/api/watch</code></div>
</p>
</div>
</div>`;
@@ -186,7 +188,8 @@ const Messages = function(props) {
method: 'post',
body: `message=${encodeURIComponent(txt)}`
}).then(r => setTxt(''));
const connstatus = props.config.connected ? 'connected' : 'disconnected';
const routing = "connected" in props.config;
const connstatus = !routing ? 'This device has no MQTT functionality' : props.config.connected ? 'connected' : 'disconnected';
return html`
<div class="section">
<h3 style="background: #30c040; color: #fff; padding: 0.4em;">MQTT messages</h3>
@@ -199,7 +202,7 @@ const Messages = function(props) {
<div style="margin: 0.5em 0; display: flex">
<span class="addon nowrap">Publish message:</span>
<input placeholder="type and press enter..." style="flex: 1 100%;"
value=${txt} onchange=${sendmessage}
value=${txt} onchange=${sendmessage} disabled=${!routing}
oninput=${ev => setTxt(ev.target.value)} />
</div>
<div class="msg">
@@ -341,7 +344,11 @@ const App = function(props) {
const login = function(u) {
document.cookie = `access_token=${u.token}; Secure, HttpOnly; SameSite=Lax; path=/; max-age=3600`;
setUser(u.user);
watch();
if (location.search.substring(1) == 'nows') {
// If query string is ?nows, then do not connect to websocket. For debug.
} else {
watch(); // Connect to websocket, receive constant graph updates
}
return getconfig();
};
+1 -1
View File
@@ -35,4 +35,4 @@ flash3:
cd build && $(ESPTOOL) --chip esp32 -p $(PORT) -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x100000 mongoose-esp32-example.bin
clean:
$(DOCKER) rm -rf build sdkconfig
test -d build && $(DOCKER) rm -rf build sdkconfig || true
@@ -1,5 +1,5 @@
THISDIR = $(realpath $(CURDIR))
ROOTDIR = $(realpath $(CURDIR)/../..)
ROOTDIR = $(realpath $(CURDIR)/../../..)
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) docker.io/mdashnet/8266
CMD ?= make -C src defconfig app
PORT ?= /dev/ttyUSB0
@@ -41,6 +41,5 @@ monitor: build
.PHONY: build
clean:
clean: CMD = rm -rf src/build
clean: build
test -d src/build && $(DOCKER) rm -rf src/build || true
File renamed without changes.
@@ -7,4 +7,4 @@
# please read the ESP-IDF documents if you need to do this.
#
COMPONENT_INCLUDES += ../../../../..
COMPONENT_INCLUDES += ../../../../../..
@@ -0,0 +1 @@
../../../../../mongoose.c
@@ -0,0 +1,524 @@
#
# Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration
#
CONFIG_IDF_TARGET_ESP8266=y
CONFIG_IDF_TARGET="esp8266"
#
# SDK tool configuration
#
CONFIG_SDK_TOOLPREFIX="xtensa-lx106-elf-"
CONFIG_SDK_PYTHON="python"
# CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES is not set
CONFIG_BOOTLOADER_INIT_SPI_FLASH=y
# CONFIG_BOOTLOADER_DISABLE_JTAG_IO is not set
# CONFIG_BOOTLOADER_FAST_BOOT is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
CONFIG_LOG_BOOTLOADER_LEVEL=3
# CONFIG_BOOTLOADER_APP_TEST is not set
CONFIG_BOOTLOADER_STORE_OFFSET=0x0
CONFIG_ESPTOOLPY_PORT="/dev/ttyACM0"
CONFIG_ESPTOOLPY_BAUD_115200B=y
# CONFIG_ESPTOOLPY_BAUD_230400B is not set
# CONFIG_ESPTOOLPY_BAUD_921600B is not set
# CONFIG_ESPTOOLPY_BAUD_2MB is not set
# CONFIG_ESPTOOLPY_BAUD_OTHER is not set
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
CONFIG_ESPTOOLPY_BAUD=115200
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set
# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set
# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set
CONFIG_ESPTOOLPY_FLASHMODE="dio"
CONFIG_SPI_FLASH_MODE=0x0
# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set
CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
CONFIG_SPI_FLASH_FREQ=0x0
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
CONFIG_SPI_FLASH_SIZE=0x400000
CONFIG_ESPTOOLPY_BEFORE_RESET=y
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
CONFIG_ESPTOOLPY_BEFORE="default_reset"
CONFIG_ESPTOOLPY_AFTER_HARD_RESET=y
# CONFIG_ESPTOOLPY_AFTER_SOFT_RESET is not set
# CONFIG_ESPTOOLPY_AFTER_NORESET is not set
CONFIG_ESPTOOLPY_AFTER="hard_reset"
# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set
# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set
# CONFIG_ESPTOOLPY_MONITOR_BAUD_74880B is not set
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set
# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set
# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set
# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set
CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=74880
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
CONFIG_PARTITION_TABLE_SINGLE_APP=y
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
# CONFIG_PARTITION_TABLE_CUSTOM is not set
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv"
CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y
# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set
# CONFIG_COMPILER_CXX_EXCEPTIONS is not set
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set
# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set
# CONFIG_COMPILER_STACK_CHECK is not set
# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set
CONFIG_APP_UPDATE_CHECK_APP_SUM=y
# CONFIG_APP_UPDATE_CHECK_APP_HASH is not set
CONFIG_APP_COMPILE_TIME_DATE=y
# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set
# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set
# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set
# CONFIG_ENABLE_COAP is not set
CONFIG_ESP_TLS_USING_MBEDTLS=y
# CONFIG_ESP_TLS_USING_WOLFSSL is not set
# CONFIG_ESP_TLS_SERVER is not set
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set
# CONFIG_ESP_WOLFSSL_INTERNAL is not set
# CONFIG_WOLFSSL_DEBUG is not set
CONFIG_ESP8266_NMI_WDT=y
# CONFIG_ESP8266_XTAL_FREQ_40 is not set
CONFIG_ESP8266_XTAL_FREQ_26=y
CONFIG_ESP8266_XTAL_FREQ=26
# CONFIG_ESP8266_DEFAULT_CPU_FREQ_80 is not set
CONFIG_ESP8266_DEFAULT_CPU_FREQ_160=y
CONFIG_ESP8266_DEFAULT_CPU_FREQ_MHZ=160
CONFIG_ESP_FILENAME_MACRO_NO_PATH=y
# CONFIG_ESP_FILENAME_MACRO_RAW is not set
# CONFIG_ESP_FILENAME_MACRO_NULL is not set
CONFIG_USING_NEW_ETS_VPRINTF=y
# CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set
CONFIG_ETS_PRINTF_EXIT_WHEN_FLASH_RW=y
# CONFIG_SOC_FULL_ICACHE is not set
CONFIG_SOC_IRAM_SIZE=0xC000
# CONFIG_DISABLE_ROM_UART_PRINT is not set
# CONFIG_ESP_PANIC_PRINT_HALT is not set
CONFIG_ESP_PANIC_PRINT_REBOOT=y
# CONFIG_ESP_PANIC_SILENT_REBOOT is not set
# CONFIG_ESP_PANIC_GDBSTUB is not set
CONFIG_RESET_REASON=y
CONFIG_WIFI_PPT_TASKSTACK_SIZE=5120
CONFIG_ESP8266_CORE_GLOBAL_DATA_LINK_IRAM=y
# CONFIG_ESP8266_OTA_FROM_OLD is not set
# CONFIG_ESP8266_BOOT_COPY_APP is not set
CONFIG_ESP8266_TIME_SYSCALL_USE_FRC1=y
# CONFIG_ESP8266_TIME_SYSCALL_USE_NONE is not set
# CONFIG_PM_ENABLE is not set
CONFIG_SCAN_AP_MAX=99
CONFIG_WIFI_TX_RATE_SEQUENCE_FROM_HIGH=y
# CONFIG_ESP8266_WIFI_QOS_ENABLED is not set
# CONFIG_ESP8266_WIFI_AMPDU_RX_ENABLED is not set
# CONFIG_ESP8266_WIFI_AMSDU_ENABLED is not set
CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=16
CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM=16
CONFIG_ESP8266_WIFI_RX_PKT_NUM=7
CONFIG_ESP8266_WIFI_TX_PKT_NUM=6
CONFIG_ESP8266_WIFI_NVS_ENABLED=y
CONFIG_ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET=y
CONFIG_ESP8266_WIFI_ENABLE_WPA3_SAE=y
# CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE is not set
CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y
# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set
CONFIG_ESP_PHY_INIT_DATA_VDD33_CONST=33
CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER=20
# CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT is not set
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584
CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
# CONFIG_ESP_CONSOLE_UART_NONE is not set
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_UART_BAUDRATE=74880
# CONFIG_ESP_UART0_SWAP_IO is not set
CONFIG_ESP_TASK_WDT=y
CONFIG_ESP_TASK_WDT_PANIC=y
# CONFIG_ESP_TASK_WDT_TIMEOUT_13N is not set
# CONFIG_ESP_TASK_WDT_TIMEOUT_14N is not set
CONFIG_ESP_TASK_WDT_TIMEOUT_15N=y
CONFIG_ESP_TASK_WDT_TIMEOUT_S=15
# CONFIG_ESP_EVENT_LOOP_PROFILING is not set
CONFIG_ESP_EVENT_POST_FROM_ISR=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set
CONFIG_HTTP_BUF_SIZE=512
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
CONFIG_HTTPD_MAX_URI_LEN=512
CONFIG_OTA_BUF_SIZE=256
# CONFIG_OTA_ALLOW_HTTP is not set
# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set
CONFIG_FATFS_CODEPAGE_437=y
# CONFIG_FATFS_CODEPAGE_720 is not set
# CONFIG_FATFS_CODEPAGE_737 is not set
# CONFIG_FATFS_CODEPAGE_771 is not set
# CONFIG_FATFS_CODEPAGE_775 is not set
# CONFIG_FATFS_CODEPAGE_850 is not set
# CONFIG_FATFS_CODEPAGE_852 is not set
# CONFIG_FATFS_CODEPAGE_855 is not set
# CONFIG_FATFS_CODEPAGE_857 is not set
# CONFIG_FATFS_CODEPAGE_860 is not set
# CONFIG_FATFS_CODEPAGE_861 is not set
# CONFIG_FATFS_CODEPAGE_862 is not set
# CONFIG_FATFS_CODEPAGE_863 is not set
# CONFIG_FATFS_CODEPAGE_864 is not set
# CONFIG_FATFS_CODEPAGE_865 is not set
# CONFIG_FATFS_CODEPAGE_866 is not set
# CONFIG_FATFS_CODEPAGE_869 is not set
# CONFIG_FATFS_CODEPAGE_932 is not set
# CONFIG_FATFS_CODEPAGE_936 is not set
# CONFIG_FATFS_CODEPAGE_949 is not set
# CONFIG_FATFS_CODEPAGE_950 is not set
CONFIG_FATFS_CODEPAGE=437
CONFIG_FATFS_LFN_NONE=y
# CONFIG_FATFS_LFN_HEAP is not set
# CONFIG_FATFS_LFN_STACK is not set
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=y
CONFIG_FMB_COMM_MODE_TCP_EN=y
CONFIG_FMB_TCP_PORT_DEFAULT=502
CONFIG_FMB_TCP_PORT_MAX_CONN=5
CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
CONFIG_FMB_QUEUE_LENGTH=20
CONFIG_FMB_PORT_TASK_STACK_SIZE=4096
CONFIG_FMB_SERIAL_BUF_SIZE=256
CONFIG_FMB_PORT_TASK_PRIO=10
CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y
CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233
CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20
CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
CONFIG_FMB_CONTROLLER_STACK_SIZE=4096
CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20
CONFIG_FMB_TIMER_GROUP=0
CONFIG_FMB_TIMER_INDEX=0
# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set
# CONFIG_DISABLE_FREERTOS is not set
CONFIG_FREERTOS_UNICORE=y
# CONFIG_FREERTOS_ENABLE_REENT is not set
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_MAX_HOOK=2
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024
CONFIG_FREERTOS_ISR_STACKSIZE=512
# CONFIG_FREERTOS_EXTENED_HOOKS is not set
CONFIG_FREERTOS_GLOBAL_DATA_LINK_IRAM=y
# CONFIG_FREERTOS_CODE_LINK_TO_IRAM is not set
CONFIG_FREERTOS_TIMER_STACKSIZE=2048
CONFIG_TASK_SWITCH_FASTER=y
# CONFIG_USE_QUEUE_SETS is not set
# CONFIG_ENABLE_FREERTOS_SLEEP is not set
# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
# CONFIG_HEAP_DISABLE_IRAM is not set
# CONFIG_HEAP_TRACING is not set
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_LOG_COLORS=y
# CONFIG_LOG_SET_LEVEL is not set
CONFIG_LWIP_LOCAL_HOSTNAME="espressif"
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
# CONFIG_LWIP_L2_TO_L3_COPY is not set
# CONFIG_LWIP_IRAM_OPTIMIZATION is not set
CONFIG_LWIP_TIMERS_ONDEMAND=y
CONFIG_LWIP_MAX_SOCKETS=10
# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set
# CONFIG_LWIP_SO_LINGER is not set
CONFIG_LWIP_SO_REUSE=y
CONFIG_LWIP_SO_REUSE_RXTOALL=y
# CONFIG_LWIP_SO_RCVBUF is not set
# CONFIG_LWIP_NETBUF_RECVINFO is not set
CONFIG_LWIP_IP4_FRAG=y
CONFIG_LWIP_IP6_FRAG=y
# CONFIG_LWIP_IP4_REASSEMBLY is not set
# CONFIG_LWIP_IP6_REASSEMBLY is not set
# CONFIG_LWIP_IP_FORWARD is not set
# CONFIG_LWIP_STATS is not set
# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set
CONFIG_LWIP_ESP_GRATUITOUS_ARP=y
CONFIG_LWIP_GARP_TMR_INTERVAL=60
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32
CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y
# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set
CONFIG_LWIP_DHCPS_LEASE_UNIT=60
CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8
# CONFIG_LWIP_AUTOIP is not set
# CONFIG_LWIP_IPV6_AUTOCONFIG is not set
CONFIG_LWIP_NETIF_LOOPBACK=y
CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8
CONFIG_LWIP_MAX_ACTIVE_TCP=16
CONFIG_LWIP_MAX_LISTENING_TCP=16
CONFIG_LWIP_TCP_MAXRTX=12
CONFIG_LWIP_TCP_SYNMAXRTX=6
CONFIG_LWIP_TCP_MSS=1440
CONFIG_LWIP_TCP_TMR_INTERVAL=250
CONFIG_LWIP_TCP_MSL=60000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=2880
CONFIG_LWIP_TCP_WND_DEFAULT=5760
CONFIG_LWIP_TCP_RECVMBOX_SIZE=6
CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
# CONFIG_LWIP_TCP_SACK_OUT is not set
# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
CONFIG_LWIP_TCP_OVERSIZE_MSS=y
# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
CONFIG_LWIP_TCP_RTO_TIME=3000
CONFIG_LWIP_MAX_UDP_PCBS=16
CONFIG_LWIP_UDP_RECVMBOX_SIZE=6
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048
CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set
CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_LWIP_PPP_SUPPORT is not set
CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3
CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
# CONFIG_LWIP_MULTICAST_PING is not set
# CONFIG_LWIP_BROADCAST_PING is not set
CONFIG_LWIP_MAX_RAW_PCBS=16
# CONFIG_LWIP_IPV6 is not set
CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
CONFIG_LWIP_ESP_LWIP_ASSERT=y
# CONFIG_LWIP_DEBUG is not set
CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set
# CONFIG_MBEDTLS_DEBUG is not set
CONFIG_MBEDTLS_HAVE_TIME=y
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set
# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set
# CONFIG_MBEDTLS_TLS_DISABLED is not set
CONFIG_MBEDTLS_TLS_SERVER=y
CONFIG_MBEDTLS_TLS_CLIENT=y
CONFIG_MBEDTLS_TLS_ENABLED=y
# CONFIG_MBEDTLS_PSK_MODES is not set
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y
CONFIG_MBEDTLS_SSL_RENEGOTIATION=y
# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set
CONFIG_MBEDTLS_SSL_PROTO_TLS1=y
CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set
CONFIG_MBEDTLS_SSL_ALPN=y
CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y
CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y
CONFIG_MBEDTLS_AES_C=y
# CONFIG_MBEDTLS_CAMELLIA_C is not set
# CONFIG_MBEDTLS_DES_C is not set
CONFIG_MBEDTLS_RC4_DISABLED=y
# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set
# CONFIG_MBEDTLS_RC4_ENABLED is not set
# CONFIG_MBEDTLS_BLOWFISH_C is not set
# CONFIG_MBEDTLS_XTEA_C is not set
CONFIG_MBEDTLS_CCM_C=y
CONFIG_MBEDTLS_GCM_C=y
# CONFIG_MBEDTLS_RIPEMD160_C is not set
CONFIG_MBEDTLS_PEM_PARSE_C=y
CONFIG_MBEDTLS_PEM_WRITE_C=y
CONFIG_MBEDTLS_X509_CRL_PARSE_C=y
CONFIG_MBEDTLS_X509_CSR_PARSE_C=y
CONFIG_MBEDTLS_ECP_C=y
CONFIG_MBEDTLS_ECDH_C=y
CONFIG_MBEDTLS_ECDSA_C=y
CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
# CONFIG_util_assert is not set
# CONFIG_ESP_SHA is not set
CONFIG_ESP_AES=y
CONFIG_ESP_MD5=y
CONFIG_ESP_ARC4=y
# CONFIG_ENABLE_MDNS is not set
CONFIG_MQTT_PROTOCOL_311=y
CONFIG_MQTT_TRANSPORT_SSL=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y
# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set
# CONFIG_MQTT_CUSTOM_OUTBOX is not set
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set
CONFIG_NEWLIB_NANO_FORMAT=y
# CONFIG_OPENSSL_DEBUG is not set
CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
# CONFIG_OPENSSL_ASSERT_EXIT is not set
CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_PTHREAD_STACK_MIN=768
CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPIFFS_MAX_PARTITIONS=3
CONFIG_SPIFFS_CACHE=y
CONFIG_SPIFFS_CACHE_WR=y
# CONFIG_SPIFFS_CACHE_STATS is not set
CONFIG_SPIFFS_PAGE_CHECK=y
CONFIG_SPIFFS_GC_MAX_RUNS=10
# CONFIG_SPIFFS_GC_STATS is not set
CONFIG_SPIFFS_PAGE_SIZE=256
CONFIG_SPIFFS_OBJ_NAME_LEN=32
CONFIG_SPIFFS_USE_MAGIC=y
CONFIG_SPIFFS_USE_MAGIC_LENGTH=y
CONFIG_SPIFFS_META_LENGTH=4
CONFIG_SPIFFS_USE_MTIME=y
# CONFIG_SPIFFS_DBG is not set
# CONFIG_SPIFFS_API_DBG is not set
# CONFIG_SPIFFS_GC_DBG is not set
# CONFIG_SPIFFS_CACHE_DBG is not set
# CONFIG_SPIFFS_CHECK_DBG is not set
# CONFIG_SPIFFS_TEST_VISUALISATION is not set
CONFIG_IP_LOST_TIMER_INTERVAL=120
CONFIG_TCPIP_ADAPTER_GLOBAL_DATA_LINK_IRAM=y
CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_VFS_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
# CONFIG_WL_SECTOR_SIZE_512 is not set
CONFIG_WL_SECTOR_SIZE_4096=y
CONFIG_WL_SECTOR_SIZE=4096
# CONFIG_ENABLE_UNIFIED_PROVISIONING is not set
CONFIG_LTM_FAST=y
CONFIG_WPA_MBEDTLS_CRYPTO=y
# CONFIG_WPA_DEBUG_PRINT is not set
# CONFIG_WPA_TESTING_OPTIONS is not set
# CONFIG_WPA_WPS_WARS is not set
# CONFIG_WPA_11KV_SUPPORT is not set
# Deprecated options for backward compatibility
CONFIG_TARGET_PLATFORM="esp8266"
CONFIG_TOOLPREFIX="xtensa-lx106-elf-"
# CONFIG_MAKE_WARN_UNDEFINED_VARIABLES is not set
CONFIG_FLASHMODE_QIO=y
# CONFIG_FLASHMODE_QOUT is not set
# CONFIG_FLASHMODE_DIO is not set
# CONFIG_FLASHMODE_DOUT is not set
# CONFIG_MONITOR_BAUD_9600B is not set
# CONFIG_MONITOR_BAUD_57600B is not set
# CONFIG_MONITOR_BAUD_74880B is not set
CONFIG_MONITOR_BAUD_115200B=y
# CONFIG_MONITOR_BAUD_230400B is not set
# CONFIG_MONITOR_BAUD_921600B is not set
# CONFIG_MONITOR_BAUD_2MB is not set
# CONFIG_MONITOR_BAUD_OTHER is not set
CONFIG_MONITOR_BAUD_OTHER_VAL=74880
CONFIG_MONITOR_BAUD=115200
CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set
CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set
# CONFIG_CXX_EXCEPTIONS is not set
CONFIG_STACK_CHECK_NONE=y
# CONFIG_STACK_CHECK_NORM is not set
# CONFIG_STACK_CHECK_STRONG is not set
# CONFIG_STACK_CHECK_ALL is not set
# CONFIG_STACK_CHECK is not set
# CONFIG_WARN_WRITE_STRINGS is not set
CONFIG_MAIN_TASK_STACK_SIZE=3584
CONFIG_CONSOLE_UART_DEFAULT=y
# CONFIG_CONSOLE_UART_CUSTOM is not set
# CONFIG_CONSOLE_UART_NONE is not set
CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=74880
# CONFIG_UART0_SWAP_IO is not set
CONFIG_TASK_WDT=y
CONFIG_TASK_WDT_PANIC=y
CONFIG_TASK_WDT_TIMEOUT_S=15
CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150
CONFIG_MB_MASTER_DELAY_MS_CONVERT=200
CONFIG_MB_QUEUE_LENGTH=20
CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096
CONFIG_MB_SERIAL_BUF_SIZE=256
CONFIG_MB_SERIAL_TASK_PRIO=10
CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y
CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233
CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20
CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
CONFIG_MB_CONTROLLER_STACK_SIZE=4096
CONFIG_MB_EVENT_QUEUE_TIMEOUT=20
CONFIG_MB_TIMER_GROUP=0
CONFIG_MB_TIMER_INDEX=0
# CONFIG_L2_TO_L3_COPY is not set
# CONFIG_USE_ONLY_LWIP_SELECT is not set
CONFIG_ESP_GRATUITOUS_ARP=y
CONFIG_GARP_TMR_INTERVAL=60
CONFIG_TCPIP_RECVMBOX_SIZE=32
CONFIG_TCP_MAXRTX=12
CONFIG_TCP_SYNMAXRTX=6
CONFIG_TCP_MSS=1440
CONFIG_TCP_MSL=60000
CONFIG_TCP_SND_BUF_DEFAULT=2880
CONFIG_TCP_WND_DEFAULT=5760
CONFIG_TCP_RECVMBOX_SIZE=6
CONFIG_TCP_QUEUE_OOSEQ=y
# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
CONFIG_TCP_OVERSIZE_MSS=y
# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_TCP_OVERSIZE_DISABLE is not set
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=2048
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_PPP_SUPPORT is not set
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_ESP32_PTHREAD_STACK_MIN=768
CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_SUPPORT_TERMIOS=y
# End of deprecated options
-1
View File
@@ -1 +0,0 @@
../../../../mongoose.c
-5
View File
@@ -22,11 +22,6 @@ static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
MG_INFO(("Last chunk received, sending response"));
mg_http_reply(c, 200, "", "ok (chunked)\n");
}
} else if (ev == MG_EV_HTTP_MSG && mg_http_match_uri(hm, "/upload")) {
MG_INFO(("Got all %lu bytes!", (unsigned long) hm->body.len));
MG_INFO(("Query string: [%.*s]", (int) hm->query.len, hm->query.ptr));
// MG_INFO(("Body:\n%.*s", (int) hm->body.len, hm->body.ptr));
mg_http_reply(c, 200, "", "ok (%lu)\n", (unsigned long) hm->body.len);
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
mg_http_serve_dir(c, hm, &opts);
+3 -3
View File
@@ -17,10 +17,10 @@ static const uint64_t s_timeout_ms = 1500; // Connect timeout in milliseconds
// Print HTTP response and signal that we're done
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_OPEN) {
// Connection created. Store connect expiration time in c->label
*(uint64_t *) c->label = mg_millis() + s_timeout_ms;
// Connection created. Store connect expiration time in c->data
*(uint64_t *) c->data = mg_millis() + s_timeout_ms;
} else if (ev == MG_EV_POLL) {
if (mg_millis() > *(uint64_t *) c->label &&
if (mg_millis() > *(uint64_t *) c->data &&
(c->is_connecting || c->is_resolving)) {
mg_error(c, "Connect timeout");
}
+2 -4
View File
@@ -35,14 +35,12 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n");
for (struct mg_connection *t = c->mgr->conns; t != NULL; t = t->next) {
char loc[40], rem[40];
mg_http_printf_chunk(c, "%-3lu %4s %s %-15s %s\n", t->id,
mg_http_printf_chunk(c, "%-3lu %4s %s %I %I\n", t->id,
t->is_udp ? "UDP" : "TCP",
t->is_listening ? "LISTENING"
: t->is_accepted ? "ACCEPTED "
: "CONNECTED",
mg_straddr(&t->loc, loc, sizeof(loc)),
mg_straddr(&t->rem, rem, sizeof(rem)));
4, &t->loc.ip, 4, &t->rem.ip);
}
mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk
} else if (mg_http_match_uri(hm, "/api/f2/*")) {
+2 -7
View File
@@ -1,10 +1,9 @@
PROG ?= example
ROOT ?= $(realpath $(CURDIR)/../..)
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_IPV6=1 -DMG_ENABLE_SSI=1
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_IPV6=1 -DMG_ENABLE_SSI=1 -DMG_HTTP_DIRLIST_TIME=1
CFLAGS ?= -I../.. -W -Wall $(DEFS) $(EXTRA)
VCFLAGS = /nologo /W3 /O2 /I../.. $(DEFS) $(EXTRA) /link /incremental:no /machine:IX86
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)
$(RUN) ./$(PROG) $(ARGS)
@@ -16,11 +15,7 @@ mongoose.exe: main.c
$(VC98) wine cl ../../mongoose.c main.c $(VCFLAGS) ws2_32.lib /out:$@
mingw:
gcc ../../mongoose.c main.c -I../.. -W -Wall -DMG_ENABLE_IPV6=1 -DMG_ENABLE_LINES=1 -D_POSIX_C_SOURCE=200000L -lws2_32 -o mongoose.exe
linux: example
#linux: CFLAGS += -O2 -fsanitize=address,undefined,shift,null,return,bounds,alignment,object-size,bool,enum -static-libasan
linux: CC = $(LIN) cc
gcc ../../mongoose.c main.c -I../.. -W -Wall $(DEFS) -D_POSIX_C_SOURCE=200000L -lws2_32 -o mongoose.exe
clean:
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mongoose mongoose_* mongoose.*
+2 -2
View File
@@ -30,7 +30,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_OPEN) {
// c->is_hexdumping = 1;
} else if (ev == MG_EV_WS_OPEN) {
c->label[0] = 'W'; // Mark this connection as an established WS client
c->data[0] = 'W'; // Mark this connection as an established WS client
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/websocket")) {
@@ -58,7 +58,7 @@ static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
// Broadcast message to all connected websocket clients.
for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
if (c->label[0] != 'W') continue;
if (c->data[0] != 'W') continue;
mg_ws_printf(c, WEBSOCKET_OP_TEXT, "{%Q:%Q,%Q:[%d,%d,%d]}", "method",
"notification1", "params", 1, 2, 3);
}
@@ -23,12 +23,12 @@ var jsonrpc = function(url, onopen, onclose, onnotification) {
ws.send(JSON.stringify(request));
console.log('sent', request);
return new Promise(function(resolve, reject) {
setTimeout(JSONRPC_TIMEOUT_MS, function() {
setTimeout(function() {
if (pending[id] === undefined) return;
log('Timing out frame ', JSON.stringify(request));
delete (pending[id]);
reject();
});
}, JSONRPC_TIMEOUT_MS);
pending[id] = x => resolve(x);
});
},
+2 -2
View File
@@ -14,7 +14,7 @@ static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_http_serve_opts opts = {.root_dir = NULL};
mg_http_serve_file(c, hm, "log.txt", &opts);
} else if (mg_http_match_uri(hm, "/api/log/live")) {
c->label[0] = 'L'; // Mark that connection as live log listener
c->data[0] = 'L'; // Mark that connection as live log listener
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
} else {
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
@@ -34,7 +34,7 @@ static void log_message(const char *filename, const char *message) {
static void broadcast_message(struct mg_mgr *mgr, const char *message) {
struct mg_connection *c;
for (c = mgr->conns; c != NULL; c = c->next) {
if (c->label[0] == 'L') mg_http_printf_chunk(c, "%s", message);
if (c->data[0] == 'L') mg_http_printf_chunk(c, "%s", message);
}
}
+12 -3
View File
@@ -1,13 +1,22 @@
PROG ?= example
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_MIP=1 -DMG_ENABLE_SOCKET=0 -DMG_ENABLE_WINSOCK=0 -I../..
CFLAGS ?= -W -Wall
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_MIP=1 -DMG_ENABLE_SOCKET=0 -DMG_ENABLE_PACKED_FS=1 -I../..
CFLAGS ?= -W -Wall $(EXTRA_CFLAGS)
LIBS ?= -lpcap
SOURCES = main.c ../../mongoose.c ../device-dashboard/net.c ../device-dashboard/packed_fs.c
ifeq "$(SSL)" "MBEDTLS"
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -lmbedtls -lmbedcrypto -lmbedx509 -I$(MBEDTLS)/include -L$(MBEDTLS)/lib
endif
ifeq "$(SSL)" "OPENSSL"
CFLAGS += -DMG_ENABLE_OPENSSL=1 -lssl -lcrypto -I$(OPENSSL)/include -L$(OPENSSL)/lib
endif
all: $(PROG)
$(RUN) ./$(PROG) $(ARGS)
$(PROG): main.c
$(CC) main.c ../../mongoose.c $(CFLAGS) $(DEFS) -o $(PROG) $(LIBS)
$(CC) $(SOURCES) $(CFLAGS) $(DEFS) -o $(PROG) $(LIBS)
clean:
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
+246
View File
@@ -0,0 +1,246 @@
# MIP TCP / IP stack over pcap
This example allows to use Mongoose's MIP built-in TCP/IP stack on systems
that support pcap API, i.e. have libpcap library installed. The application
opens an interface and uses `pcap_next_ex()` for reading packets from the
interface, and `pcap_inject()` to write packets to the interface.
NOTE: depending on the libcap implementation, the injected packets may
or may not be looped back to the interface's TCP/IP stack. If they are
not looped back, then it is necessary to create a separate interface that
is bridged to the target interface - see MacOS example below.
## MacOS setup
MacOS has support for `feth` (fake ethernet) interfaces. One can create a pair
of `feth` interfaces and interlink them. Once a `feth` interface is assigned
a peer and an IP address, anything that gets injected to it, appears on a
peer interface and vice versa.
```sh
$ sudo ifconfig feth0 create
$ sudo ifconfig feth1 create
$ sudo ifconfig feth1 peer feth0 # Link two fake ethernet ifaces together
$ sudo ifconfig feth1 10.10 # Assign 10.0.0.10 to feth1
$ sudo ifconfig feth0 up
$ sudo ifconfig feth1 up
```
Now we have two Ethernet interfaces, `feth0` and `feth1`, interlinked and
active. On your Mac, go to "System Preferences" / Sharing, enable "Internet
Sharing" and choose "Thunderbolt bridge". This enables DHCP on the `bridge0`
interface, which is bridge for all Thunderbolt devices, and adds necessary
routes to the WiFi interface. On my system it gets `192.168.2.1` IP address,
and serves `192.168.2/24` net. We should add one of our fake interfaces to
this bridge:
```sh
$ sudo ifconfig bridge0 addm feth1
```
We can start an example using the `feth0`:
```sh
$ make -C examples/mip-pcap/ clean all ARGS="-i feth0"
...
2386718 3 mip.c:279:arp_cache_add ARP cache: added 0xc0a80201 @ 36:77:4d:be:e0:80
2386718 2 mip.c:300:onstatechange READY, IP: 192.168.2.17
```
The diagram of the setup is below:
```
┌──────────► 192.168.2.1 bridge0
│ routing DHCP │
│ ┌──────────────────┴──────────────────┐
▼ │ │ 192.168.2.17
│ ┌─────────┐ fake ethernet pair ┌─────────┐
192.168.0.10 │ │ feth1 ├────────────┬───────┤ feth0 │
┌─────────┐ │ └─────────┘ │ └────┬────┘
│ en0 │ │ │ │
└────┬────┘ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ en1 │ │ en2 │ │ en3 │ │ mip-pcap
│ └────┬────┘ └────┬────┘ └────┬────┘ │
WiFi │ │ │ │ │
└──────┼───────────┼───────────┼──────┘
│ │ │ │
▼
Internet Thunderbolt Ethernet
```
## Linux setup
The quick and simple options are:
- Open your loopback device (probably `lo`), in which case MIP is only reachable from your machine, and MIP also sees echoes of its own traffic.
- Open your Ethernet/WiFi device (probably `eth0` or `enpXsY` for Ethernet), in which case MIP can access the network and the Internet but is not reachable from within your machine
- If you happen to have a virtual bridge interface (for linking several virtual machines together, for example) (probably `br0` or `virbr0`), you can open it, but it will behave as opening the underlying physical interface.
For best results, you should create a virtual interface, which you can use as is, attach to a virtual bridge, or forward/masquerade its traffic.
```sh
$ sudo ip link add my0 type veth peer [name] my1
$ sudo ip link set my0 up
$ sudo ip link set my1 up
```
In some systems, like for example RHEL7, _name_ is mandatory; in others you might need not to add it, that is why we represented it here using square brackets.
### Use a virtual interface
This is similar to using the loopback device, MIP is only reachable from the hosting machine, but you can add forwarding and masquerading later. Once you have your virtual interface up and running with an IP address, you can configure any services on one end, let's say `my1`, while you open the other end, `my0` with MIP.
- Add an IP address to one end of the pipe
```sh
$ sudo ip addr add 192.168.0.1/24 dev my1
```
- Start your DHCP server at that interface serving that subnet, or otherwise configure MIP to use a fixed address within that subnet.
- Now start the example opening the other end of the virtual interface:
```sh
$ make -C examples/mip-pcap/ clean all ARGS="-i my0"
```
- In some systems, you will probably need superuser privileges to open the device:
```sh
$ sudo examples/mip-pcap/example -i my0
```
```
[DHCP server for 192.168.0.x]
192.168.0.1 192.168.0.x
┌─────────┐ virtual eth pair ┌─────────┐
│ my1 ├────────────────────┤ my0 │
└─────────┘ └────┬────┘
│
│
mip-pcap
```
As you can't access any other host than your workstation, you need to add any required services (as DNS) there, and configure Mongoose appropriately. This is a foundation, you can expand it by choosing one of the solutions that follow.
### Bridge to your network
We will attach one end of the virtual interface to a bridge, which will also be attached to your network interface. In this case, MIP will have access to your network (and through it, to the Internet) and will also be reachable from your own workstation and other hosts in your network. You don't need to add IP addresses as in the example above, unless you don't have a DHCP server in your network, in which case you will configure MIP for a fixed address in your subnet.
- If you don't already have a virtual bridge interface, as mentioned above, you'll have to create it and attach your network interface (NIC) to it. Your IP address has to be assigned to the bridge, instead of the NIC. If you are using DHCP, the client must run on the bridge interface instead of the NIC.
```sh
$ ip link add virbr0 type bridge
$ sudo ip link set virbr0 up
$ sudo ip addr del 10.1.0.10/24 dev enp9s0
$ sudo ip link set enp9s0 master virbr0
$ sudo ip addr add 10.1.0.10/24 dev virbr0
```
Check using `ifconfig`, and try to ping some host in your network
- Attach one end of the virtual interface to the bridge:
```sh
$ sudo ip link set my1 master virbr0
```
- If everything is fine, you'll see your interface pair state is UP:
```sh
$ ip link show master virbr0
2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UP mode DEFAULT group default qlen 1000
link/ether 30:5a:3a:08:db:90 brd ff:ff:ff:ff:ff:ff
396: my1@my0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr0 state UP mode DEFAULT group default qlen 1000
link/ether b6:ee:bc:53:f2:6e brd ff:ff:ff:ff:ff:ff
```
- Now start the example opening the other end of the virtual interface:
```sh
$ make -C examples/mip-pcap/ clean all ARGS="-i my0"
```
- In some systems, you will probably need superuser privileges to open the device:
```sh
$ sudo examples/mip-pcap/example -i my0
```
```
10.1.0.10
virbr0
│
┌──────────────────┴──────────────────┐
│ │ 10.1.0.x
│ ┌─────────┐ virtual eth pair ┌─────────┐
│ │ my1 ├────────────┬───────┤ my0 │
│ └─────────┘ │ └────┬────┘
│ │ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ vnet1 │ │ enp9s0 │ │ vnet2 │ │ mip-pcap
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
└──────┼───────────┼───────────┼──────┘
│ │ │
│
Ethernet [WiFi]
│ Local LAN 10.1.0.x
│ DHCP server, router
▼
Internet
```
If you have _Docker_ running, it may introduce firewall rules that will disrupt your bridging.
### Forward/Masquerade
Once you have your virtual interface up and running with an IP address, you can use your Linux to NAT and forward MIP traffic to another interface, for example the one that connects you to the Internet. In this case, MIP will have access to the Internet and will also be reachable from your own workstation; but not from any other hosts in your local network (if there is one). You can use this setup with a direct connection to the Internet or being part of a network, when you want to isolate MIP from the rest of your network.
- We assume you already have a firewall in place (you should); to configure masquerading and forwarding do:
```sh
$ sudo iptables -t nat -A POSTROUTING -o enp9s0 -j MASQUERADE
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```
Remember to use the proper network interface name
- Now start the example opening the other end of the virtual interface:
```sh
$ make -C examples/mip-pcap/ clean all ARGS="-i my0"
```
- In some systems, you will probably need superuser privileges to open the device:
```sh
$ sudo examples/mip-pcap/example -i my0
```
```
[DHCP server for 192.168.0.x]
┌────────────► 192.168.0.1 192.168.0.x
│ forwarding ┌─────────┐ virtual eth pair ┌─────────┐
│ masquerading │ my1 ├────────────────────┤ my0 │
│ └─────────┘ └────┬────┘
▼ │
Your IP (LAN / Public) │
┌─────────┐ mip-pcap
│ enp9s0 │
└────┬────┘
│
│
Ethernet
│
▼
Internet
```
You can also use this setup if your NIC is part of a bridge (for example: you have virtual machines); in that case:
- use the bridge interface for masquerading, instead of the Ethernet (your IP now belongs to the virtual bridge, not the NIC):
```sh
$ sudo iptables -t nat -A POSTROUTING -o virbr0 -j MASQUERADE
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```
Remember to use the proper bridge interface name
```
[DHCP server for 192.168.0.x]
10.1.0.10 ◀──────────────► 192.168.0.1 192.168.0.x
virbr0 forwarding ┌─────────┐ virtual eth pair ┌─────────┐
│ masquerading │ my1 ├────────────────────┤ my0 │
│ └─────────┘ └────┬────┘
┌──────────────────┴──────────────────┐ │
│ │ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ mip-pcap
│ │ vnet1 │ │ enp9s0 │ │ vnet2 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
└──────┼───────────┼───────────┼──────┘
│ │ │
│
Ethernet [WiFi]
│ Local LAN 10.1.0.x
│ DHCP server, router
▼
Internet
```
+1
View File
@@ -0,0 +1 @@
../../test/data/ca.pem
+73 -52
View File
@@ -6,73 +6,84 @@
#include <pcap.h>
#include "mongoose.h"
static struct mg_connection *s_sntp_conn = NULL;
#define MQTT_URL "mqtt://broker.hivemq.com:1883" // MQTT broker to connect to
#define MQTT_TOPIC "t/123" // Topic to subscribe to
#if MG_ARCH == MG_ARCH_WIN32
#define usleep(x) Sleep((x) / 1000)
#endif
static int s_signo;
void signal_handler(int signo) {
s_signo = signo;
}
// SNTP client callback
static void sfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_SNTP_TIME) {
int64_t t = *(int64_t *) ev_data;
MG_INFO(("Got SNTP time: %lld ms from epoch", t));
} else if (ev == MG_EV_CLOSE) {
s_sntp_conn = NULL;
}
(void) fn_data, (void) c;
}
// Called every 5 seconds. Increase that for production case.
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
if (s_sntp_conn == NULL) s_sntp_conn = mg_sntp_connect(mgr, NULL, sfn, NULL);
if (s_sntp_conn != NULL) mg_sntp_request(s_sntp_conn);
}
static int fail(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
return EXIT_FAILURE;
}
static size_t pcap_tx(const void *data, size_t len, void *userdata) {
int res = pcap_inject((pcap_t *) userdata, data, len);
static size_t pcap_tx(const void *buf, size_t len, struct mip_if *ifp) {
int res = pcap_inject((pcap_t *) ifp->driver_data, buf, len);
if (res == PCAP_ERROR) {
MG_ERROR(("pcap_inject: %d", res));
}
return len;
return res == PCAP_ERROR ? 0 : len;
}
static bool pcap_status(void *userdata) {
return userdata ? true : false;
static bool pcap_up(struct mip_if *ifp) {
return ifp->driver_data ? true : false;
}
static size_t pcap_rx(void *buf, size_t len, void *userdata) {
static size_t pcap_rx(void *buf, size_t len, struct mip_if *ifp) {
size_t received = 0;
struct pcap_pkthdr *hdr = NULL;
const unsigned char *pkt = NULL;
if (pcap_next_ex((pcap_t *) userdata, &hdr, &pkt) == 1) {
usleep(1000); // Sleep 1 millisecond. This is to avoid 100% CPU
if (pcap_next_ex((pcap_t *) ifp->driver_data, &hdr, &pkt) == 1) {
received = hdr->len < len ? hdr->len : len;
memcpy(buf, pkt, received);
}
return received;
}
static void fn2(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;
MG_DEBUG(("Got response (%d) %.*s...", (int) hm->message.len, 12,
hm->message.ptr));
c->is_closing = 1;
} else if (ev == MG_EV_CONNECT) {
mg_printf(c, "GET %s HTTP/1.1\r\n\r\n", mg_url_uri((char *) fn_data));
} else if (ev == MG_EV_CLOSE) {
free(fn_data);
}
}
static void fn(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;
if (mg_http_match_uri(hm, "/api/debug")) {
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
mg_log_set(level);
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
} else if (mg_http_match_uri(hm, "/api/url")) {
char *url = mg_json_get_str(hm->body, "$.url");
if (url == NULL) {
mg_http_reply(c, 200, NULL, "no url, rl %d\r\n", (int) c->recv.len);
} else {
mg_http_connect(c->mgr, url, fn2, url);
mg_http_reply(c, 200, NULL, "ok\r\n");
}
} else {
mg_http_reply(c, 200, NULL, "%.*s\r\n", (int) hm->message.len,
hm->message.ptr);
}
}
(void) ev_data, (void) fn_data;
}
int main(int argc, char *argv[]) {
const char *iface = "lo0"; // Network iface
const char *mac = "aa:bb:cc:01:02:03"; // MAC address
const char *mac = "02:00:01:02:03:77"; // MAC address
const char *bpf = NULL; // "host x.x.x.x or ether host ff:ff:ff:ff:ff:ff";
char errbuf[PCAP_ERRBUF_SIZE] = "";
struct mg_mgr mgr; // Event manager
mg_mgr_init(&mgr); // Initialise event manager
mg_log_set(MG_LL_DEBUG); // Set debug log level
mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, &mgr);
// Parse options
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-i") == 0 && i + 1 < argc) {
@@ -81,8 +92,11 @@ int main(int argc, char *argv[]) {
mac = argv[++i];
} else if (strcmp(argv[i], "-bpf") == 0 && i + 1 < argc) {
bpf = argv[++i];
} else if (strcmp(argv[i], "-v") == 0 && i + 1 < argc) {
mg_log_set(atoi(argv[++i]));
} else {
return fail("unknown option %s", argv[i]);
MG_ERROR(("unknown option %s", argv[i]));
return EXIT_FAILURE;
}
}
@@ -97,32 +111,39 @@ int main(int argc, char *argv[]) {
}
pcap_freealldevs(devs);
}
fail("pcap_open_live: %s\n", errbuf);
return EXIT_FAILURE;
}
pcap_setnonblock(ph, 1, errbuf);
pcap_setdirection(ph, PCAP_D_IN);
// Apply BPF to reduce noise. Let in only broadcasts and our own traffic
if (bpf != NULL) {
struct bpf_program bpfp;
if (pcap_compile(ph, &bpfp, bpf, 1, 0)) fail("compile \n");
if (pcap_compile(ph, &bpfp, bpf, 1, 0)) MG_ERROR(("BPF compile failed\n"));
pcap_setfilter(ph, &bpfp);
pcap_freecode(&bpfp);
}
MG_INFO(("Opened interface %s\n", iface));
MG_INFO(("Opened interface %s", iface));
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
struct mip_ipcfg ipcfg = {.ip = 0, .mask = 0, .gw = 0};
sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &ipcfg.mac[0], &ipcfg.mac[1],
&ipcfg.mac[2], &ipcfg.mac[3], &ipcfg.mac[4], &ipcfg.mac[5]);
struct mg_mgr mgr; // Event manager
mg_mgr_init(&mgr); // Initialise event manager
mg_log_set(MG_LL_DEBUG); // Set log level
struct mip_driver driver = {
.tx = pcap_tx, .status = pcap_status, .rx = pcap_rx};
mip_init(&mgr, &ipcfg, &driver, ph);
struct mip_driver driver = {.tx = pcap_tx, .up = pcap_up, .rx = pcap_rx};
struct mip_if mif = {.driver = &driver, .driver_data = ph};
sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mif.mac[0], &mif.mac[1],
&mif.mac[2], &mif.mac[3], &mif.mac[4], &mif.mac[5]);
mip_init(&mgr, &mif);
MG_INFO(("Init done, starting main loop"));
while (s_signo == 0) mg_mgr_poll(&mgr, 1); // Infinite event loop
// extern void device_dashboard_fn(struct mg_connection *, int, void *, void
// *);
mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, &mgr);
while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop
mg_mgr_free(&mgr);
pcap_close(ph);
+22
View File
@@ -0,0 +1,22 @@
PROG ?= example
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_MIP=1 -DMG_ENABLE_SOCKET=0 -DMG_ENABLE_PACKED_FS=1 -I../..
CFLAGS ?= -W -Wall $(EXTRA_CFLAGS)
LIBS ?=
SOURCES = main.c ../../mongoose.c ../device-dashboard/net.c ../device-dashboard/packed_fs.c
ifeq "$(SSL)" "MBEDTLS"
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -lmbedtls -lmbedcrypto -lmbedx509 -I$(MBEDTLS)/include -L$(MBEDTLS)/lib
endif
ifeq "$(SSL)" "OPENSSL"
CFLAGS += -DMG_ENABLE_OPENSSL=1 -lssl -lcrypto -I$(OPENSSL)/include -L$(OPENSSL)/lib
endif
all: $(PROG)
$(RUN) ./$(PROG) $(ARGS)
$(PROG): main.c
$(CC) $(SOURCES) $(CFLAGS) $(DEFS) -o $(PROG) $(LIBS)
clean:
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
+173
View File
@@ -0,0 +1,173 @@
# MIP TCP / IP stack on a tap interface
This example allows the use of Mongoose's MIP built-in TCP/IP stack in systems that support a TUN/TAP device. The application opens a TAP device and uses the standard socket interface to read and write on it.
The interface can be created by the example itself, but it will also disappear when the example exits. Since we usually need to do something before, like setting up a DHCP server or establishing some connections to the rest of the world, we'll manually create a specific TAP interface and the example will open it; this way, we can have everything setup in advance.
## Linux setup
Create a TAP interface; you can use it as is, attach it to a virtual bridge, or forward/masquerade its traffic.
```sh
$ sudo ip tuntap add dev tap0 mode tap
$ sudo ip link set tap0 up
```
In some systems, you might need superuser privileges to open the device with the example. In others, you can add `user yourusername` or `group yourgroup` at creation time, to grant access to it.
### Use as a virtual interface
In this scenario, MIP is only reachable from the hosting machine, but you can add forwarding and masquerading later. Once you have your TAP interface up and running with an IP address, you can configure any services on it.
- Add an IP address
```sh
$ sudo ip addr add 192.168.0.1/24 dev tap0
```
- Start your DHCP server at that interface serving that subnet, or otherwise configure MIP to use a fixed address within that subnet.
- Now start the example opening the very same TAP interface:
```sh
$ make -C examples/mip-tap/ clean all
```
If you are using a different interface name than `tap0`, add `ARGS="-i ifcname"`, and use the proper interface name
```
[DHCP server for 192.168.0.x]
192.168.0.1 192.168.0.x
┌─────────┐
│ tap0 ├──────────────────── mip-tap
└─────────┘
```
As you can't access any other host than your workstation, you need to add any required services (as DNS) there, and configure Mongoose appropriately. This is a foundation, you can expand it by choosing one of the solutions that follow.
### Bridge to your network
If you happen to have a virtual bridge interface (for linking several virtual machines together, for example) (probably `br0` or `virbr0`), we can take advantage of it.
We will attach one end of the virtual interface to a bridge, which will also be attached to your network interface. In this case, MIP will have access to your network (and through it, to the Internet) and will also be reachable from your own workstation and other hosts in your network. You don't need to add IP addresses as in the example above, unless you don't have a DHCP server in your network, in which case you will configure MIP for a fixed address in your subnet.
- If you don't already have a virtual bridge interface, as mentioned above, you'll have to create it and attach your network interface (NIC) to it. Your IP address has to be assigned to the bridge, instead of the NIC. If you are using DHCP, the client must run on the bridge interface instead of the NIC.
```sh
$ ip link add virbr0 type bridge
$ sudo ip link set virbr0 up
$ sudo ip addr del 10.1.0.10/24 dev enp9s0
$ sudo ip link set enp9s0 master virbr0
$ sudo ip addr add 10.1.0.10/24 dev virbr0
```
Check using `ifconfig`, and try to ping some host in your network
- Attach the TAP interface to the bridge:
```sh
$ sudo ip link set tap0 master virbr0
```
- You won't see your interface state is UP until it is open, but you can check you see something like this:
```sh
$ ip link show master virbr0
2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UP mode DEFAULT group default qlen 1000
link/ether 30:5a:3a:08:db:90 brd ff:ff:ff:ff:ff:ff
6: tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT group default qlen 1000
link/ether 66:91:e2:5f:d7:ed brd ff:ff:ff:ff:ff:ff
```
- Now start the example
```sh
$ make -C examples/mip-tap/ clean all
```
If you are using a different interface name than `tap0`, add `ARGS="-i ifcname"`, and use the proper interface name
- Now if everything is fine, besides the example working, you'll see your interface state is UP:
```sh
$ ip link show master virbr0
2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UP mode DEFAULT group default qlen 1000
link/ether 30:5a:3a:08:db:90 brd ff:ff:ff:ff:ff:ff
6: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UP mode DEFAULT group default qlen 1000
link/ether 66:91:e2:5f:d7:ed brd ff:ff:ff:ff:ff:ff
```
```
10.1.0.10
virbr0
│
┌──────────────────┴──────────────────┐
│ │ 10.1.0.x
│ ┌────────┐ │
│ │ tap0 ├─────────────┼─────── mip-tap
│ └────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ vnet1 │ │ enp9s0 │ │ vnet2 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
└──────┼───────────┼───────────┼──────┘
│ │ │
│
Ethernet [WiFi]
│ Local LAN 10.1.0.x
│ DHCP server, router
▼
Internet
```
If you have _Docker_ running, it may introduce firewall rules that will disrupt your bridging.
### Forward/Masquerade
Once you have your virtual interface up and running with an IP address, you can use your Linux to NAT and forward MIP traffic to another interface, for example the one that connects you to the Internet. In this case, MIP will have access to the Internet and will also be reachable from your own workstation; but not from any other hosts in your local network (if there is one). You can use this setup with a direct connection to the Internet or being part of a network, when you want to isolate MIP from the rest of your network.
- We assume you already have a firewall in place (you should); to configure masquerading and forwarding do:
```sh
$ sudo iptables -t nat -A POSTROUTING -o enp9s0 -j MASQUERADE
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```
Remember to use the proper network interface name
- Now start the example
```sh
$ make -C examples/mip-tap/ clean all
```
If you are using a different interface name than `tap0`, add `ARGS="-i ifcname"`, and use the proper interface name
```
[DHCP server for 192.168.0.x]
┌────────────► 192.168.0.1 192.168.0.x
│ forwarding ┌─────────┐
│ masquerading │ tap0 ├──────────────────── mip-tap
│ └─────────┘
▼
Your IP (LAN / Public)
┌─────────┐
│ enp9s0 │
└────┬────┘
│
│
Ethernet
│
▼
Internet
```
You can also use this setup if your NIC is part of a bridge (for example: you have virtual machines); in that case:
- use the bridge interface for masquerading, instead of the Ethernet (your IP now belongs to the virtual bridge, not the NIC):
```sh
$ sudo iptables -t nat -A POSTROUTING -o virbr0 -j MASQUERADE
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```
Remember to use the proper bridge interface name
```
[DHCP server for 192.168.0.x]
10.1.0.10 ◀──────────────► 192.168.0.1 192.168.0.x
virbr0 forwarding ┌─────────┐
│ masquerading │ tap0 ├──────────────────── mip-tap
│ └─────────┘
┌──────────────────┴──────────────────┐
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ vnet1 │ │ enp9s0 │ │ vnet2 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
└──────┼───────────┼───────────┼──────┘
│ │ │
│
Ethernet [WiFi]
│ Local LAN 10.1.0.x
│ DHCP server, router
▼
Internet
```
+1
View File
@@ -0,0 +1 @@
../../test/data/ca.pem
+116
View File
@@ -0,0 +1,116 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
//
// example using MIP and a TUN/TAP interface
static const char *s_listening_address = "http://0.0.0.0:8000";
#include <sys/socket.h>
#ifndef __OpenBSD__
#include <linux/if.h>
#include <linux/if_tun.h>
#else
#include <net/if.h>
#include <net/if_tun.h>
#include <net/if_types.h>
#endif
#include <sys/ioctl.h>
#include "mongoose.h"
static int s_signo;
void signal_handler(int signo) {
s_signo = signo;
}
static size_t tap_tx(const void *buf, size_t len, struct mip_if *ifp) {
ssize_t res = write(*(int*) ifp->driver_data, buf, len);
if (res < 0) {
MG_ERROR(("tap_tx failed: %d", errno));
return 0;
}
return (size_t) res;
}
static bool tap_up(struct mip_if *ifp) {
return ifp->driver_data ? true : false;
}
static size_t tap_rx(void *buf, size_t len, struct mip_if *ifp) {
ssize_t received = read(*(int *) ifp->driver_data, buf, len);
usleep(1); // This is to avoid 100% CPU
if (received < 0) return 0;
return (size_t) received;
}
int main(int argc, char *argv[]) {
const char *iface = "tap0"; // Network iface
const char *mac = "02:00:01:02:03:77"; // MAC address
// Parse options
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-i") == 0 && i + 1 < argc) {
iface = argv[++i];
} else if (strcmp(argv[i], "-mac") == 0 && i + 1 < argc) {
mac = argv[++i];
} else if (strcmp(argv[i], "-v") == 0 && i + 1 < argc) {
mg_log_set(atoi(argv[++i]));
} else {
MG_ERROR(("unknown option %s", argv[i]));
return EXIT_FAILURE;
}
}
// Open network interface
#ifndef __OpenBSD__
const char* tuntap_device = "/dev/net/tun";
#else
const char* tuntap_device = "/dev/tap0";
#endif
int fd = open(tuntap_device, O_RDWR);
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, iface, IFNAMSIZ);
#ifndef __OpenBSD__
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
MG_ERROR(("Failed to setup TAP interface: %s", ifr.ifr_name));
abort(); // return EXIT_FAILURE;
}
#else
ifr.ifr_flags = (short)(IFF_UP | IFF_BROADCAST | IFF_MULTICAST);
if (ioctl(fd, TUNSIFMODE, (void *) &ifr) < 0) {
MG_ERROR(("Failed to setup TAP interface: %s", ifr.ifr_name));
abort(); // return EXIT_FAILURE;
}
#endif
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); // Non-blocking mode
MG_INFO(("Opened TAP interface: %s", iface));
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
struct mg_mgr mgr; // Event manager
mg_mgr_init(&mgr); // Initialise event manager
struct mip_driver driver = {.tx = tap_tx, .up = tap_up, .rx = tap_rx};
struct mip_if mif = {.driver = &driver, .driver_data = &fd};
sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mif.mac[0], &mif.mac[1],
&mif.mac[2], &mif.mac[3], &mif.mac[4], &mif.mac[5]);
mip_init(&mgr, &mif);
MG_INFO(("Init done, starting main loop"));
// Start infinite event loop
MG_INFO(("Mongoose version : v%s", MG_VERSION));
MG_INFO(("Listening on : %s", s_listening_address));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *);
mg_http_listen(&mgr, s_listening_address, device_dashboard_fn, &mgr);
while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop
mg_mgr_free(&mgr);
close(fd);
printf("Exiting on signal %d\n", s_signo);
return 0;
}
+2 -2
View File
@@ -55,13 +55,13 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
MG_INFO(("Connected to %s", s_url));
MG_INFO(("Subscribing to %s", s_rx_topic));
mg_mqtt_sub(c, topic, s_qos);
c->label[0] = 'X'; // Set a label that we're logged in
c->data[0] = 'X'; // Set a label that we're logged in
} else if (ev == MG_EV_MQTT_MSG) {
// When we receive MQTT message, print it
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
MG_INFO(("Received on %.*s : %.*s", (int) mm->topic.len, mm->topic.ptr,
(int) mm->data.len, mm->data.ptr));
} else if (ev == MG_EV_POLL && c->label[0] == 'X') {
} else if (ev == MG_EV_POLL && c->data[0] == 'X') {
static unsigned long prev_second;
unsigned long now_second = (*(unsigned long *) ev_data) / 1000;
if (now_second != prev_second) {
+6
View File
@@ -108,6 +108,12 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
}
break;
}
case MQTT_CMD_PINGREQ: {
// The server must send a PINGRESP packet in response to a PINGREQ packet [MQTT-3.12.4-1]
MG_INFO(("PINGREQ %p -> PINGRESP", c->fd));
mg_mqtt_send_header(c, MQTT_CMD_PINGRESP, 0, 0);
break;
}
}
} else if (ev == MG_EV_ACCEPT) {
// c->is_hexdumping = 1;
+28
View File
@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(pico_rmii_ethernet)
# initialize the Pico SDK
pico_sdk_init()
add_compile_definitions(
MIP_DEBUG=1
MG_ENABLE_PACKED_FS=1
MG_ENABLE_MIP=1
)
add_executable(firmware
driver_rp2040_rmii.c
main.c
mongoose.c
)
# enable usb output, disable uart output
pico_enable_stdio_usb(firmware 1)
pico_enable_stdio_uart(firmware 0)
target_link_libraries(firmware hardware_pio hardware_dma pico_stdlib)
# create map/bin/hex file etc.
pico_add_extra_outputs(firmware)
+16
View File
@@ -0,0 +1,16 @@
SDK_VERSION ?= 1.4.0
SDK_REPO ?= https://github.com/raspberrypi/pico-sdk
all example:
true
build: pico-sdk
test -d build || mkdir build
cd build && cmake .. && make
pico-sdk:
git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@
cd $@ && git submodule update --init
clean:
rm -rf pico-sdk build
+63
View File
@@ -0,0 +1,63 @@
# RMII with the PIO in an RP2040 for 10Mbps Ethernet
- Full-duplex 10Mbps
- RMII Tx implemented with a PIO state machine and single-buffer DMA transfers
- Once the DMA starts sending to the PIO, subsequent attempts to tx will block
- RMII Rx implemented with a PIO state machine and ping-pong buffer DMA transfers
- PIO code handles the CSR_DV signal, stops and raises an IRQ on frame ending. CRC is calculated later for minimum dead time between frames
- SMI implemented with a PIO state machine
- The RP2040 is clocked from the LAN8720 and works at 50MHz
- CRC calculation uses a fast table-based algorithm that doesn't require much storage (nibble calculation)
## Hardware connections
You can change most pins at will, bear in mind that each function requires consecutive pins, see main.c
The RETCLK (should be REFCLK...) pin can go to either GPIO20 or GPIO22
| LAN8720 | | Raspberry Pi Pico | |
| ----------- | ----------- |----------------- | -- |
| 1,2 | VCC | 3V3 | 36 |
| 3,4 | GND | GND | 38 |
| 5 | MDC | GPIO15 | 20 |
| 6 | MDIO | GPIO14 | 19 |
| 7 | CRS | GPIO8 | 11 |
| 8 | nINT / RETCLK | GPIO20 | 26 |
| 9 | RX1 | GPIO7 | 10 |
| 10 | RX0 | GPIO6 | 9 |
| 11 | TX0 | GPIO10 | 14 |
| 12 | TX-EN | GPIO12 | 16 |
| 13 |
| 14| TX1 | GPIO11 | 15 |
## Build and run
Clone Mongoose repo, go to this example, and build it:
```sh
git clone https://github.com/cesanta/mongoose
cd mongoose/examples/rp2040/pico-rmii
make build
```
This will generate a firmware file: `build/firmware.uf2`. Reboot your Pico board in bootloader mode, and copy it to the RPI disk.
Attach to the serial console, wait a couple of seconds, then plug in your Ethernet cable:
```
$ picocom /dev/ttyACM0 -i -b 115200 --imap=lfcrlf
6213 1 mongoose.c:6757:onstatechange Link up
6217 3 mongoose.c:6840:tx_dhcp_discover DHCP discover sent
621b 3 mongoose.c:6723:arp_cache_add ARP cache: added 192.168.69.2 @ 52:54:...
6222 2 mongoose.c:6749:onstatechange READY, IP: 192.168.69.243
6227 2 mongoose.c:6750:onstatechange GW: 192.168.69.1
622b 2 mongoose.c:6752:onstatechange Lease: 21600 sec
```
Note the acquired IP address printed (you can also check your DHCP server). Point your browser to that address, or run curl, you should see an "ok" message:
```
$ curl 192.168.69.243
ok
```
@@ -0,0 +1,366 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "hardware/dma.h"
#include "hardware/pio.h"
#include "pico/stdlib.h"
#include "driver_rp2040_rmii.h"
#include "mongoose.h"
#define RXSM 0
#define TXSM 1
#define SMITXSM 2
#define SMIRXSM 0 // pio1
static uint smi_wr_addr, smi_rd_addr;
static int dma_rx;
static int dma_tx;
static dma_channel_config dmacfg_rx;
static dma_channel_config dmacfg_tx;
// Max frame size with VLAN tag + CRC and excluding preamble
#define ETH_PKT_SIZE 1522
static uint8_t s_rxbuf[2][ETH_PKT_SIZE]; // ping-pong buffer
static uint8_t s_txbuf[ETH_PKT_SIZE];
static struct mip_if *s_ifp; // MIP interface
#define rmii_tx_wrap_target 0
#define rmii_tx_wrap 8
static const uint16_t rmii_tx_program_instructions[] = {
// .wrap_target
0xe000, // 0: set pins, 0 side 0
0x80a0, // 1: pull block side 0
0xe03d, // 2: set x, 29 side 0
0xf101, // 3: set pins, 1 side 1 [1]
0x1144, // 4: jmp x--, 4 side 1 [1]
0xf103, // 5: set pins, 3 side 1 [1]
0x7002, // 6: out pins, 2 side 1
0x10e6, // 7: jmp !osre, 6 side 1
// .wrap
};
static const struct pio_program rmii_tx_program = {
.instructions = rmii_tx_program_instructions,
.length = 9,
.origin = -1,
};
static inline pio_sm_config rmii_tx_program_get_default_config(uint addr) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, addr + rmii_tx_wrap_target, addr + rmii_tx_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
static inline void rmii_tx_init(PIO pio, uint sm, uint addr, uint gpio) {
pio_sm_config c = rmii_tx_program_get_default_config(addr);
pio_gpio_init(pio, gpio);
pio_gpio_init(pio, gpio + 1);
pio_gpio_init(pio, gpio + 2);
sm_config_set_out_pins(&c, gpio, 2);
sm_config_set_set_pins(&c, gpio, 2);
sm_config_set_sideset_pins(&c, gpio + 2);
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 3, true);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
sm_config_set_out_shift(&c, true, true, 8); // pull bytes, LSB first, auto
sm_config_set_clkdiv(&c,
5); // Run at 50/5 = 10MHz (2x 2-bit nibble data rate)
pio_sm_init(pio, sm, addr, &c);
pio_sm_set_enabled(pio, sm, true);
}
#define rmii_rx_wrap_target 0
#define rmii_rx_wrap 10
static const uint16_t rmii_rx_program_instructions[] = {
// .wrap_target
0x2122, // 0: wait 0 pin, 2 [1]
0x21a2, // 1: wait 1 pin, 2 [1]
0x21a0, // 2: wait 1 pin, 0 [1]
0x2121, // 3: wait 0 pin, 1 [1]
0x21a1, // 4: wait 1 pin, 1 [1]
0x4002, // 5: in pins, 2
0x00c5, // 6: jmp pin, 5
0x4002, // 7: in pins, 2
0x00c5, // 8: jmp pin, 5
0xa0c3, // 9: mov isr, null
0xc020, // 10: irq wait 0
// .wrap
};
static const struct pio_program rmii_rx_program = {
.instructions = rmii_rx_program_instructions,
.length = 11,
.origin = -1,
};
static inline pio_sm_config rmii_rx_program_get_default_config(uint addr) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, addr + rmii_rx_wrap_target, addr + rmii_rx_wrap);
return c;
}
static inline void rmii_rx_init(PIO pio, uint sm, uint addr, uint gpio) {
pio_sm_config c = rmii_rx_program_get_default_config(addr);
pio_gpio_init(pio, gpio);
pio_gpio_init(pio, gpio + 1);
pio_gpio_init(pio, gpio + 2);
sm_config_set_in_pins(&c, gpio);
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 3, false);
sm_config_set_jmp_pin(&c, gpio + 2);
sm_config_set_in_shift(&c, true, true, 8); // push bytes, LSB first, auto
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
sm_config_set_clkdiv(&c,
5); // Run at 50/5 = 10MHz (2x 2-bit nibble data rate)
pio_sm_init(pio, sm, addr, &c);
pio_sm_set_enabled(pio, sm, true);
}
#define smi_wr_wrap_target 0
#define smi_wr_wrap 4
static const uint16_t smi_wr_program_instructions[] = {
// .wrap_target
0xe03f, // 0: set x, 31 side 0
0xe101, // 1: set pins, 1 side 0 [1]
0x1141, // 2: jmp x--, 1 side 1 [1]
0x6101, // 3: out pins, 1 side 0 [1]
0x1103, // 4: jmp 3 side 1 [1]
// .wrap
};
static const struct pio_program smi_wr_program = {
.instructions = smi_wr_program_instructions,
.length = 5,
.origin = -1,
};
static inline pio_sm_config smi_wr_program_get_default_config(uint addr) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, addr + smi_wr_wrap_target, addr + smi_wr_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#define smi_rd_wrap_target 13
#define smi_rd_wrap 13
static const uint16_t smi_rd_program_instructions[] = {
0xe03f, // 0: set x, 31 side 0
0xe101, // 1: set pins, 1 side 0 [1]
0x1141, // 2: jmp x--, 1 side 1 [1]
0xf02d, // 3: set x, 13 side 1
0x6101, // 4: out pins, 1 side 0 [1]
0x1144, // 5: jmp x--, 4 side 1 [1]
0xe180, // 6: set pindirs, 0 side 0 [1]
0xf101, // 7: set pins, 1 side 1 [1]
0xa142, // 8: nop side 0 [1]
0xf12f, // 9: set x, 15 side 1 [1]
0xa042, // 10: nop side 0
0x4001, // 11: in pins, 1 side 0
0x114a, // 12: jmp x--, 10 side 1 [1]
// .wrap_target
0xf081, // 13: set pindirs, 1 side 1
// .wrap
};
static const struct pio_program smi_rd_program = {
.instructions = smi_rd_program_instructions,
.length = 14,
.origin = -1,
};
static inline pio_sm_config smi_rd_program_get_default_config(uint addr) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, addr + smi_rd_wrap_target, addr + smi_rd_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
static inline void smi_wr_init(PIO pio, uint sm, uint addr, uint gpio) {
pio_gpio_init(pio, gpio);
pio_gpio_init(pio, gpio + 1);
pio_sm_config c = smi_wr_program_get_default_config(addr);
sm_config_set_out_pins(&c, gpio, 1);
sm_config_set_set_pins(&c, gpio, 1);
sm_config_set_sideset_pins(&c, gpio + 1);
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 2, true);
sm_config_set_out_shift(&c, false, true,
16); // pull half-words, MSB first, auto
sm_config_set_clkdiv(&c, 6); // Run at 50/6 = <10MHz (4x data rate)
pio_sm_init(pio, sm, addr, &c);
}
static inline void smi_rd_init(PIO pio, uint sm, uint addr, uint gpio) {
pio_gpio_init(pio, gpio);
pio_gpio_init(pio, gpio + 1);
pio_sm_config c = smi_rd_program_get_default_config(addr);
sm_config_set_in_pins(&c, gpio);
sm_config_set_out_pins(&c, gpio, 1);
sm_config_set_set_pins(&c, gpio, 1);
sm_config_set_sideset_pins(&c, gpio + 1);
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 2, true);
sm_config_set_out_shift(&c, false, true,
16); // pull half-words, MSB first, auto
sm_config_set_in_shift(&c, false, true,
16); // push half-words, MSB first, auto
sm_config_set_clkdiv(&c, 6); // Run at 50/6 = <10MHz (4x data rate)
pio_sm_init(pio, sm, addr, &c);
}
static inline uint32_t crc_calc(const uint8_t *data, int length) {
static const uint32_t crclut[16] = {
// table for polynomial 0xEDB88320 (reflected)
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
uint32_t crc = 0xFFFFFFFF;
while (--length >= 0) {
uint8_t byte = *data++;
crc = crclut[(crc ^ byte) & 0x0F] ^ (crc >> 4);
crc = crclut[(crc ^ (byte >> 4)) & 0x0F] ^ (crc >> 4);
}
return ~crc;
}
static void eth_write_phy(int addr, int reg, int val, uint8_t gpio) {
uint16_t op = 0x5002 | (addr << 7) | (reg << 2); // b0101aaaaarrrrr10
smi_wr_init(pio0, SMITXSM, smi_wr_addr, gpio);
pio_sm_put(pio0, SMITXSM, op << 16);
pio_sm_put(pio0, SMITXSM, (uint16_t) val << 16);
pio_sm_set_enabled(pio0, SMITXSM, true);
}
static uint16_t eth_read_phy(uint addr, uint reg, uint8_t gpio) {
uint16_t op = 0x6000 | (addr << 7) | (reg << 2); // b0110aaaaarrrrr00
smi_rd_init(pio1, SMIRXSM, smi_rd_addr, gpio);
pio_sm_put(pio1, SMIRXSM, op << 16);
pio_sm_set_enabled(pio1, SMIRXSM, true);
uint16_t val = (uint16_t) pio_sm_get_blocking(pio1, SMIRXSM);
pio_sm_set_enabled(pio1, SMIRXSM, false);
return val;
}
static void rx_irq(void);
static bool mip_driver_rp2040_rmii_init(struct mip_if *ifp) {
struct mip_driver_rp2040_rmii_data *d =
(struct mip_driver_rp2040_rmii_data *) ifp->driver_data;
uint rx_sm_addr, tx_sm_addr;
s_ifp = ifp;
if (ifp->queue.len == 0) ifp->queue.len = 8192;
rx_sm_addr = pio_add_program(pio0, &rmii_rx_program);
tx_sm_addr = pio_add_program(pio0, &rmii_tx_program);
smi_wr_addr = pio_add_program(pio0, &smi_wr_program);
smi_rd_addr = pio_add_program(pio1, &smi_rd_program);
dma_tx = dma_claim_unused_channel(true);
dmacfg_tx = dma_channel_get_default_config(dma_tx);
channel_config_set_read_increment(&dmacfg_tx, true); // read from memory
channel_config_set_write_increment(&dmacfg_tx, false); // write to FIFO
channel_config_set_dreq(&dmacfg_tx, pio_get_dreq(pio0, TXSM, true));
channel_config_set_transfer_data_size(&dmacfg_tx,
DMA_SIZE_8); // transfer bytes
rmii_tx_init(pio0, TXSM, tx_sm_addr, d->tx0);
eth_write_phy(d->phy_addr, 4, 0x61,
d->mdio); // Auto Negotiation Advertisement Register: enable
// only 10BASE-T full and half duplex (two-pair), use
// IEEE 802.3 format
sleep_us(31); // give some time for PIO to work (64 bits @2.5MHz = 25.6 us)
eth_write_phy(d->phy_addr, 0, 0x1000,
d->mdio); // Basic Control Register: enable Auto-Negotiation
sleep_us(31);
dma_rx = dma_claim_unused_channel(true);
dmacfg_rx = dma_channel_get_default_config(dma_rx);
channel_config_set_read_increment(&dmacfg_rx, false); // read from FIFO
channel_config_set_write_increment(&dmacfg_rx,
true); // write to memory, increment
channel_config_set_dreq(&dmacfg_rx, pio_get_dreq(pio0, RXSM, false));
channel_config_set_transfer_data_size(&dmacfg_rx,
DMA_SIZE_8); // transfer bytes
dma_channel_configure(dma_rx, &dmacfg_rx, s_rxbuf[0],
((uint8_t *) &pio0->rxf[RXSM]) + 3, ETH_PKT_SIZE, true);
pio_set_irq0_source_enabled(pio0, pis_interrupt0,
true); // enable SM0 on PIO0_IRQ_0
irq_set_exclusive_handler(7, rx_irq); // set handler for PIO0_IRQ_0
irq_set_enabled(7, true); // enable it
rmii_rx_init(pio0, RXSM, rx_sm_addr, d->rx0);
return true;
}
static size_t mip_driver_rp2040_rmii_tx(const void *buf, size_t len,
struct mip_if *ifp) {
dma_channel_wait_for_finish_blocking(dma_tx);
memset(s_txbuf, 0, 60); // pre-pad
memcpy(s_txbuf, buf, len);
if (len < 60) len = 60; // pad
uint32_t crc = crc_calc(s_txbuf, len); // host is little-endian
memcpy(s_txbuf + len, (uint8_t *) &crc, 4);
len += 4;
sleep_us(10); // enforce IFG in case software has been lightning fast...
dma_channel_configure(dma_tx, &dmacfg_tx, ((uint8_t *) &pio0->txf[TXSM]) + 3,
s_txbuf, len, true);
return len;
}
static uint32_t s_rxno;
// The max amount of time we should keep the PIO state machine stopped is the
// IFG time (10us) and that includes irq latency
static void rx_irq(void) {
dma_channel_hw_t *hw = dma_channel_hw_addr(dma_rx);
uint32_t rxno =
(s_rxno + 1) &
1; // 2 buffers, switch to the available one as fast as possible
size_t len = ETH_PKT_SIZE - hw->transfer_count;
dma_channel_abort(dma_rx);
dma_channel_set_write_addr(dma_rx, s_rxbuf[rxno], true); // restart DMA
pio_interrupt_clear(pio0,
0); // ACK PIO IRQ so the state machine resumes receiving
// NOTE(scaprile) Here we could check addressing to avoid queuing frames not
// for us, or we can defer that for later as we do with CRC The max amount of
// time we can linger here is what it takes for the other buffer to fill
// (<8us) and that includes irq chaining
if (len >= 64 && len <= ETH_PKT_SIZE)
mip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
s_rxno = rxno;
}
static size_t mip_driver_rp2040_rmii_rx(void *buf, size_t buflen, struct mip_if *ifp) {
size_t len = mip_qread(buf, ifp);
if (len == 0) return 0;
len -= 4; // exclude CRC from frame length
uint32_t crc = crc_calc(buf, len); // calculate CRC and compare
// NOTE(scaprile) Here we could check addressing to avoid delivering frames
// not for us, though MIP already does that (now ?)
if (memcmp(&((uint8_t *) buf)[len], &crc,
sizeof(crc))) // host is little-endian
return 0;
return len;
}
static bool mip_driver_rp2040_rmii_up(struct mip_if *ifp) {
struct mip_driver_rp2040_rmii_data *d =
(struct mip_driver_rp2040_rmii_data *) ifp->driver_data;
uint32_t bsr =
eth_read_phy(d->phy_addr, 1, d->mdio); // Basic Status Register
return (bsr & (1 << 2)) ? 1 : 0; // check Link Status flag
}
struct mip_driver mip_driver_rp2040_rmii = {
mip_driver_rp2040_rmii_init,
mip_driver_rp2040_rmii_tx,
mip_driver_rp2040_rmii_rx,
mip_driver_rp2040_rmii_up,
};
@@ -0,0 +1,10 @@
#pragma once
struct mip_driver_rp2040_rmii_data {
uint8_t rx0; // RX0, RX1, CRS_DV; consecutive GPIO pins
uint8_t tx0; // TX0, TX1, TX-EN; consecutive GPIO pins
uint8_t mdio; // MDIO, MDC; consecutive GPIO pins
uint8_t phy_addr; // PHY address
};
extern struct mip_driver mip_driver_rp2040_rmii;
+55
View File
@@ -0,0 +1,55 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "pico/stdlib.h"
#include "hardware/clocks.h"
#include "mongoose.h"
#include "driver_rp2040_rmii.h"
#define CLKREFPIN 20 // either 20 or 22
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
mg_http_reply(c, 200, "", "ok\n");
}
}
int main(void) {
// use the RMII reference clock (50MHz) as our system clock
clock_configure_gpin(clk_sys, CLKREFPIN, 50 * MHZ, 50 * MHZ);
sleep_ms(100);
stdio_init_all();
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the MIP interface
mg_log_set(MG_LL_DEBUG); // Set log level
MG_INFO(("Init MIP"));
// Initialise Mongoose network stack and specific driver
// Set consecutive GPIOs for RMII (tx and rx) and SMI function groups
struct mip_driver_rp2040_rmii_data driver_data = {
// see driver_rp2040_rmii.h
.rx0 = 6, // 6, 7, 8 : RX0, RX1, CRS_DV
.tx0 = 10, // 10, 11, 12 : TX0, TX1, TX-EN
.mdio = 14, // 14, 15 : MDIO, MDC
.phy_addr = 1 // check your hardware, LAN8722 is 0 or 1
};
// Specify MAC address, either set use_dhcp or enter a static config.
// For static configuration, specify IP/mask/GW in network byte order
struct mip_if mif = {
.mac = {2, 0, 1, 2, 3, 5},
.ip = 0,
.driver = &mip_driver_rp2040_rmii,
.driver_data = &driver_data,
};
mip_init(&mgr, &mif);
mg_http_listen(&mgr, "http://0.0.0.0", fn, NULL); // HTTP listener
MG_INFO(("Init done, starting main loop"));
for (;;) mg_mgr_poll(&mgr, 0); // Infinite event loop
return 0;
}
+1
View File
@@ -0,0 +1 @@
../../../mongoose.c
+1
View File
@@ -0,0 +1 @@
../../../mongoose.h
@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
../../../mongoose.c
../../device-dashboard/net.c
../../device-dashboard/packed_fs.c
pico-sdk//lib/tinyusb/examples/device/net_lwip_webserver/src/usb_descriptors.c
pico-sdk/lib/tinyusb/lib/networking/rndis_reports.c)
target_include_directories(firmware PUBLIC
.
../../..
pico-sdk/lib/tinyusb/lib/networking)
target_link_libraries(firmware pico_stdlib hardware_spi tinyusb_device)
pico_add_extra_outputs(firmware)
pico_enable_stdio_usb(firmware 0) # Route stdio
pico_enable_stdio_uart(firmware 1) # to the UART
# Mongoose build flags
add_definitions(-DMG_ENABLE_MIP=1)
add_definitions(-DMG_ENABLE_PACKED_FS=1)
add_definitions(-DMG_ENABLE_FILE=0)
add_definitions(-DDISABLE_ROUTING=1)
@@ -0,0 +1,16 @@
SDK_VERSION ?= 1.4.0
SDK_REPO ?= https://github.com/raspberrypi/pico-sdk
example:
true
all build: pico-sdk
test -d build || mkdir build
cd build && cmake .. && make
pico-sdk:
git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@
cd $@ && git submodule update --init
clean:
rm -rf pico-sdk build
@@ -0,0 +1,21 @@
# Device Dashboard via RNDIS on an RP2040
Your headless Raspberry Pi Pico-based hardware can also have a device dashboard on a web browser when you connect it to your computer via USB
## Build and run
Clone Mongoose repo, go to this example, and build it:
```sh
git clone https://github.com/cesanta/mongoose
cd mongoose/examples/rp2040/pico-rndis-dashboard
make build
```
This will generate a firmware file: `build/firmware.uf2`. Reboot your Pico board in bootloader mode, and copy it to the RPI disk.
The device will reboot, register as a USB RNDIS device, and add a network to your computer.
Run a browser, and open 192.168.3.1, you should see a device dashboard
Note: USB stdio in the Pico-SDK is done in background with TinyUSB and an interrupt to hide it from the user and periodically call tusb_task(). When we use TinyUSB, that code is removed from the compilation list; so this example uses UART stdio (UART 0) to keep things simple and focused on the RNDIS example. If you want to see the console output, connect an USB-to-UART or a low-voltage-TTL-to-RS-232 adapter to GPIO0
@@ -0,0 +1,81 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#include "pico/stdlib.h"
#include "tusb.h"
static struct mip_if *s_ifp;
const uint8_t tud_network_mac_address[6] = {2, 2, 0x84, 0x6A, 0x96, 0};
static void blink_cb(void *arg) { // Blink periodically
gpio_put(PICO_DEFAULT_LED_PIN, !gpio_get_out_level(PICO_DEFAULT_LED_PIN));
(void) arg;
}
bool tud_network_recv_cb(const uint8_t *buf, uint16_t len) {
mip_qwrite((void *) buf, len, s_ifp);
// MG_INFO(("RECV %hu", len));
// mg_hexdump(buf, len);
tud_network_recv_renew();
return true;
}
void tud_network_init_cb(void) {}
uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
// MG_INFO(("SEND %hu", arg));
memcpy(dst, ref, arg);
return arg;
}
static size_t usb_tx(const void *buf, size_t len, struct mip_if *ifp) {
if (!tud_ready()) return 0;
while (!tud_network_can_xmit(len)) tud_task();
tud_network_xmit((void *) buf, len);
(void) ifp;
return len;
}
static bool usb_up(struct mip_if *ifp) {
(void) ifp;
return tud_inited() && tud_ready() && tud_connected();
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_dta) {
if (ev == MG_EV_HTTP_MSG) return mg_http_reply(c, 200, "", "ok\n");
}
int main(void) {
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
stdio_init_all();
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the MIP interface
mg_timer_add(&mgr, 500, MG_TIMER_REPEAT, blink_cb, &mgr);
struct mip_driver driver = {.tx = usb_tx, .rx = mip_driver_rx, .up = usb_up};
struct mip_if mif = {.mac = {2, 0, 1, 2, 3, 0x77},
.ip = mg_htonl(MG_U32(192, 168, 3, 1)),
.mask = mg_htonl(MG_U32(255, 255, 255, 0)),
.enable_dhcp_server = true,
.driver = &driver,
.queue.len = 4096};
s_ifp = &mif;
mip_init(&mgr, &mif);
tusb_init();
MG_INFO(("Initialising application..."));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *);
mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
tud_task();
}
return 0;
}
@@ -0,0 +1,2 @@
#pragma once
#define SIZEOF_ETH_HDR 14
@@ -0,0 +1,11 @@
#pragma once
#define CFG_TUD_ECM_RNDIS 1
#if 0
#define CFG_TUD_MSC 1 // This enables mass storage
#define CFG_TUD_MSC_EP_BUFSIZE 512 // Also Add msc_disk.c and descritprs
#endif
#define CFG_TUD_NCM 0
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
@@ -0,0 +1,248 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* 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.
*
*/
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB]
*/
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5) )
// String Descriptor Index
enum
{
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
STRID_INTERFACE,
STRID_MAC
};
enum
{
ITF_NUM_CDC = 0,
ITF_NUM_CDC_DATA,
ITF_NUM_TOTAL
};
enum
{
#if CFG_TUD_ECM_RNDIS
CONFIG_ID_RNDIS = 0,
CONFIG_ID_ECM = 1,
#else
CONFIG_ID_NCM = 0,
#endif
CONFIG_ID_COUNT
};
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
tusb_desc_device_t const desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
// Use Interface Association Descriptor (IAD) device class
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0xCafe,
.idProduct = USB_PID,
.bcdDevice = 0x0101,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = CONFIG_ID_COUNT // multiple configurations
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void)
{
return (uint8_t const *) &desc_device;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN)
#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN)
#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_NCM_DESC_LEN)
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x82
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x83
#else
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x82
#endif
#if CFG_TUD_ECM_RNDIS
static uint8_t const rndis_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE),
};
static uint8_t const ecm_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU),
};
#else
static uint8_t const ncm_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM+1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU),
};
#endif
// Configuration array: RNDIS and CDC-ECM
// - Windows only works with RNDIS
// - MacOS only works with CDC-ECM
// - Linux will work on both
static uint8_t const * const configuration_arr[2] =
{
#if CFG_TUD_ECM_RNDIS
[CONFIG_ID_RNDIS] = rndis_configuration,
[CONFIG_ID_ECM ] = ecm_configuration
#else
[CONFIG_ID_NCM ] = ncm_configuration
#endif
};
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL;
}
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
// array of pointer to string descriptors
static char const* string_desc_arr [] =
{
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "TinyUSB", // Manufacturer
[STRID_PRODUCT] = "TinyUSB Device", // Product
[STRID_SERIAL] = "123456", // Serial
[STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description
// STRID_MAC index is handled separately
};
static uint16_t _desc_str[32];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
{
(void) langid;
unsigned int chr_count = 0;
if (STRID_LANGID == index)
{
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
}
else if (STRID_MAC == index)
{
// Convert MAC address into UTF-16
for (unsigned i=0; i<sizeof(tud_network_mac_address); i++)
{
_desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf];
_desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf];
}
}
else
{
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = (uint8_t) strlen(str);
if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1;
// Convert ASCII string into UTF-16
for (unsigned int i=0; i<chr_count; i++)
{
_desc_str[1+i] = str[i];
}
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
return _desc_str;
}
+13
View File
@@ -0,0 +1,13 @@
NAME = raspberry-pi-pico-w
$(NAME):
git clone --depth 1 https://github.com/mongoose-examples/$(NAME)
build: | $(NAME)
cp ./../../../mongoose.[ch] $(NAME)
cp ./../../device-dashboard/packed_fs.c $(NAME)
cp ./../../device-dashboard/net.c $(NAME)
make -C $(NAME) build
clean:
rm -rf $(NAME)
+23
View File
@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
../../../mongoose.c
../../device-dashboard/net.c
../../device-dashboard/packed_fs.c)
target_include_directories(firmware PUBLIC ../../..)
target_link_libraries(firmware pico_stdlib hardware_spi)
pico_add_extra_outputs(firmware)
# Enable USB output. Comment out in order to use UART
pico_enable_stdio_usb(firmware 0)
pico_enable_stdio_uart(firmware 1)
# Mongoose build flags
add_definitions(-DMG_ENABLE_MIP=1)
add_definitions(-DMG_ENABLE_PACKED_FS=1)
add_definitions(-DMG_ENABLE_FILE=0)
+23
View File
@@ -0,0 +1,23 @@
SDK_VERSION ?= 1.4.0
SDK_REPO ?= https://github.com/raspberrypi/pico-sdk
all example build build/firmware.uf2: pico-sdk main.c
test -d build || mkdir build
cd build && cmake .. && make
pico-sdk:
git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@
cd $@ && git submodule update --init
# Requires env variable VCON_API_KEY set
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/3
test: update
curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
grep 'Ethernet: up' /tmp/output.txt
grep 'MQTT connected' /tmp/output.txt
update: build/firmware.uf2
curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @$<
clean:
rm -rf pico-sdk build
+57
View File
@@ -0,0 +1,57 @@
# RP2040 with W5500 Ethernet module
This repository demonstrates how to use RP2040 with W5500 Ethernet module,
to implement networking. In this example, a very simple HTTP server is
implemented. See [other examples](../..) for more functionality.
## RP2040 Pico wiring
The W5500 module uses SPI for communication. The following pins are used
by this example (modify `main.c` if you use a different pinout):
```c
enum { LED = 25, SPI_CS = 17, SPI_CLK = 18, SPI_TX = 19, SPI_RX = 16 };
```
On a breadboard, it might look like this:
![](images/wiring.png)
## Pinout reference
![](images/pinout.png)
## Build and run
Clone Mongoose repo, go to this example, and build it:
```sh
git clone https://github.com/cesanta/mongoose
cd mongoose/examples/ro2040/pico-w5500
make
```
The above will make a firmware in `build/example.uf2`. Reboot your Pico
board in bootloader mode, and copy `example.uf2` to the RPI disk.
Attach serial console. Then, plug in Ethernet cable:
```
$ cu -l /dev/cu.usb* -s 115200
4653 2 main.c:79:main Ethernet: down
520b 2 main.c:79:main Ethernet: down
5dc3 2 main.c:79:main Ethernet: down
6593 1 mongoose.c:6757:onstatechange Link up
659a 3 mongoose.c:6840:tx_dhcp_discover DHCP discover sent
667b 3 mongoose.c:6723:arp_cache_add ARP cache: added 192.168.0.1 @ 90:5c:44:55:19:8b
667d 2 mongoose.c:6749:onstatechange READY, IP: 192.168.0.24
667e 2 mongoose.c:6750:onstatechange GW: 192.168.0.1
6680 2 mongoose.c:6752:onstatechange Lease: 86062 sec
697b 2 main.c:79:main Ethernet: up
7533 2 main.c:79:main Ethernet: up
```
Note the aquired IP address printed. Run a browser, and type that IP address
in the address field. You should see an "ok" message in a browser:
![](images/browser.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

+71
View File
@@ -0,0 +1,71 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
#include <stdio.h>
#include <string.h>
#include "hardware/spi.h"
#include "pico/stdlib.h"
#include "mongoose.h"
enum { BLINK_PERIOD_MS = 1000 };
enum { LED = 25, SPI_CS = 17, SPI_CLK = 18, SPI_TX = 19, SPI_RX = 16 }; // Pins
static void spi_begin(void *spi) { gpio_put(SPI_CS, 0); }
static void spi_end(void *spi) { gpio_put(SPI_CS, 1); }
static uint8_t spi_txn(void *spi, uint8_t byte) {
uint8_t result = 0;
spi_write_read_blocking(spi0, &byte, &result, 1);
return result;
}
static void timer_cb(void *arg) {
gpio_put(PICO_DEFAULT_LED_PIN, !gpio_get_out_level(PICO_DEFAULT_LED_PIN));
bool up = ((struct mip_if *) arg)->state == MIP_STATE_READY;
MG_INFO(("Ethernet: %s", up ? "up" : "down")); // Show network status
}
int main(void) {
stdio_init_all();
MG_INFO(("Starting ..."));
// Init LED
gpio_init(LED);
gpio_set_dir(LED, GPIO_OUT);
// Init SPI pins
spi_init(spi0, 500 * 1000);
gpio_set_function(SPI_RX, GPIO_FUNC_SPI); // MISO
gpio_set_function(SPI_TX, GPIO_FUNC_SPI); // MOSI
gpio_set_function(SPI_CLK, GPIO_FUNC_SPI); // CLK
gpio_init(SPI_CS); // CS
gpio_set_dir(SPI_CS, GPIO_OUT); // Set CS it to output
gpio_put(SPI_CS, 1); // And drive CS high (inactive)
// Init Mongoose
struct mip_spi spi = {NULL, spi_begin, spi_end, spi_txn};
struct mip_if mif = {.mac = {2, 0, 1, 2, 3, 5},
.driver = &mip_driver_w5500,
.driver_data = &spi};
struct mg_mgr mgr; // Declare event manager
mg_mgr_init(&mgr); // Init event manager
mg_log_set(MG_LL_DEBUG); // Set DEBUG log level
mip_init(&mgr, &mif); // Init TCP/IP stack
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_cb, &mif);
MG_INFO(("Waiting until network is up..."));
while (mif.state != MIP_STATE_READY) {
mg_mgr_poll(&mgr, 0);
}
MG_INFO(("Initialising application..."));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *);
mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 1);
}
return 0;
}
+20
View File
@@ -0,0 +1,20 @@
PROG ?= example
CFLAGS ?= -W -Wall -Wextra -O2 $(EXTRA_CFLAGS)
SSL ?= MBEDTLS
ifeq "$(SSL)" "MBEDTLS"
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -lmbedtls -lmbedcrypto -lmbedx509 -L$(MBEDTLS)/lib -I$(MBEDTLS)/include
endif
ifeq "$(SSL)" "OPENSSL"
CFLAGS += -DMG_ENABLE_OPENSSL=1 -lssl -lcrypto -L$(OPENSSL)/lib -I$(OPENSSL)/include
endif
all: $(PROG)
$(RUN) ./$(PROG) $(ARGS)
$(PROG): main.c
$(CC) ../../mongoose.c -I../.. $(CFLAGS) -o $(PROG) main.c
clean:
rm -rf $(PROG) _CL* *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mbedtls
+5
View File
@@ -0,0 +1,5 @@
# SMTP client example
This example shows how to send emails using Mongoose.
Before running this example, open main.c and modify settings at the top
of the file.
+1
View File
@@ -0,0 +1 @@
../../test/data/ca.pem
+82
View File
@@ -0,0 +1,82 @@
#include "mongoose.h"
static const char *server =
"tcp://mail.domain.com:587"; // Change this! Your mail server and port
static const char *user = "aaa@domain.com"; // Change this! Your mail account
static const char *pass = "xxxxxxxxxxxxxx"; // Change this! Your mail password
static const char *to = "bbb@domain.com"; // Change this! Destination email
static const char *from = "My Mail Sender";
static const char *subj = "Test email from Mongoose library!";
static const char *mesg = "Hi!\nThis is a test message.\nBye.";
static bool s_quit;
enum { EHLO, STARTTLS, STARTTLS_WAIT, AUTH, FROM, TO, DATA, BODY, QUIT, END };
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
uint8_t *state = (uint8_t *) c->data;
if (ev == MG_EV_OPEN) {
// c->is_hexdumping = 1;
} else if (ev == MG_EV_READ) {
if (c->recv.len > 0 && c->recv.buf[c->recv.len - 1] == '\n') {
MG_INFO(("<-- %.*s", (int) c->recv.len - 2, c->recv.buf));
c->recv.len = 0;
if (*state == EHLO) {
mg_printf(c, "EHLO myname\r\n");
*state = STARTTLS;
} else if (*state == STARTTLS) {
mg_printf(c, "STARTTLS\r\n");
*state = STARTTLS_WAIT;
} else if (*state == STARTTLS_WAIT) {
struct mg_tls_opts opts = {.ca = "ca.pem"};
mg_tls_init(c, &opts);
*state = AUTH;
} else if (*state == AUTH) {
char a[100], b[300] = "";
size_t n = mg_snprintf(a, sizeof(a), "%c%s%c%s", 0, user, 0, pass);
mg_base64_encode((uint8_t *) a, n, b);
mg_printf(c, "AUTH PLAIN %s\r\n", b);
*state = FROM;
} else if (*state == FROM) {
mg_printf(c, "MAIL FROM: <%s>\r\n", user);
*state = TO;
} else if (*state == TO) {
mg_printf(c, "RCPT TO: <%s>\r\n", to);
*state = DATA;
} else if (*state == DATA) {
mg_printf(c, "DATA\r\n");
*state = BODY;
} else if (*state == BODY) {
mg_printf(c, "From: %s <%s>\r\n", from, user); // Mail header
mg_printf(c, "Subject: %s\r\n", subj); // Mail header
mg_printf(c, "\r\n"); // End of headers
mg_printf(c, "%s\r\n", mesg); // Mail body
mg_printf(c, ".\r\n"); // End of body
*state = QUIT;
} else if (*state == QUIT) {
mg_printf(c, "QUIT\r\n");
*state = END;
} else {
c->is_draining = 1;
MG_INFO(("end"));
}
MG_INFO(("--> %.*s", (int) c->send.len - 2, c->send.buf));
}
} else if (ev == MG_EV_CLOSE) {
s_quit = true;
} else if (ev == MG_EV_TLS_HS) {
MG_INFO(("TLS handshake done! Sending EHLO again"));
mg_printf(c, "EHLO myname\r\n");
}
(void) fn_data, (void) ev_data;
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr);
// mg_log_set(MG_LL_VERBOSE);
mg_connect(&mgr, server, fn, NULL);
while (s_quit == false) mg_mgr_poll(&mgr, 1000);
return 0;
}
+5 -5
View File
@@ -55,7 +55,7 @@ static void handshake(struct mg_connection *c) {
}
mg_iobuf_del(r, 0, 2 + r->buf[1]);
mg_send(c, reply, sizeof(reply));
c->label[0] = STATE_REQUEST;
c->data[0] = STATE_REQUEST;
}
}
@@ -146,15 +146,15 @@ static void request(struct mg_connection *c) {
}
mg_send(c, r->buf + 3, addr_len + 1 + 2);
mg_iobuf_del(r, 0, 6 + addr_len); // Remove request from the input stream
c->label[0] = STATE_ESTABLISHED; // Mark ourselves as connected
c->data[0] = STATE_ESTABLISHED; // Mark ourselves as connected
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_READ) {
// We use the first label byte as a state
if (c->label[0] == STATE_HANDSHAKE) handshake(c);
if (c->label[0] == STATE_REQUEST) request(c);
if (c->label[0] == STATE_ESTABLISHED) exchange(c);
if (c->data[0] == STATE_HANDSHAKE) handshake(c);
if (c->data[0] == STATE_REQUEST) request(c);
if (c->data[0] == STATE_ESTABLISHED) exchange(c);
} else if (ev == MG_EV_CLOSE) {
disband(c);
}
@@ -0,0 +1,35 @@
CFLAGS ?= -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion \
-Wformat-truncation -fno-common -Wconversion \
-g3 -Os -ffunction-sections -fdata-sections -I. \
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 $(EXTRA_CFLAGS)
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = boot.c main.c syscalls.c
# Add Mongoose-specific flags and source files
CFLAGS += -I../../.. -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 -DMG_ENABLE_MIP=1 -DMG_ENABLE_PACKED_FS=1
SOURCES += ../../../mongoose.c ../../device-dashboard/net.c ../../device-dashboard/packed_fs.c
all build example: firmware.bin
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
firmware.elf: $(SOURCES) mcu.h
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
# Note: on "unknown chip id" flash error, wire BOOT0 to VDD and st-flash erase
flash: firmware.bin
st-flash --reset write $< 0x8000000
# Requires env variable VCON_API_KEY set
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/2
test: update
curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
grep 'Ethernet: up' /tmp/output.txt
grep 'MQTT connected' /tmp/output.txt
update: firmware.bin
curl --fail -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$<
clean:
@rm -rf firmware.* *.su
@@ -0,0 +1,44 @@
# Baremetal webserver on NUCLEO-F429ZI
This firmware uses MIP, an experimental TCP/IP stack of the Mongoose Network Library,
which implements the following:
- A complete [HTTP device dashboard](../../device-dashboard) with:
- User authentication
- Real-time device data graph
- Coninfiguration display and update
- MQTT communication with a remote MQTT server
- No dependencies: no HAL, no CMSIS, no RTOS
- Hand-written [mcu.h](mcu.h) header based on a [datasheet](https://www.st.com/resource/en/reference_manual/rm0090-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-advanced-armbased-32bit-mcus-stmicroelectronics.pdf)
- Interrupt-driven [Ethernet driver](../../../drivers/mip_driver_stm32.c)
- Blue LED blinky, based on SysTick interrupt
- User button handler, turns off/on green LED, based on EXTI, interrupt-driven
- HardFault handler that blinks red LED
- Debug log on UART3 (st-link)
## Requirements
- [GNU make](http://mongoose.ws/tutorials/tools/#gnu-make)
- [ARM GCC](http://mongoose.ws/tutorials/tools/#arm-gcc)
- [stlink](http://mongoose.ws/tutorials/tools/#stlink) for flashing
The links above will send you to tutorials on how to install each of those tools in your workstation for Linux, Mac, and Windows.
## Usage
Plugin your Nucleo board into USB, and attach an Ethernet cable.
To build and flash:
```sh
$ make clean flash
```
To see debug log, use any serial monitor program like `picocom` at 115200 bps and configure it to insert carriage returns after line feeds:
```sh
$ picocom /dev/ttyACM0 -i -b 115200 --imap=lfcrlf
```
There is also a [detailed tutorial on this example](https://mongoose.ws/tutorials/stm32/nucleo-f746zg-baremetal/) but for the NUCLEO-F746ZG board
For more details and benchmark data on MIP, check the [F746ZG example](../nucleo-f746zg-baremetal/)
@@ -0,0 +1,160 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
// Startup code
__attribute__((naked, noreturn)) void _reset(void) {
// Initialise memory
extern long _sbss, _ebss, _sdata, _edata, _sidata;
for (long *src = &_sbss; src < &_ebss; src++) *src = 0;
for (long *src = &_sdata, *dst = &_sidata; src < &_edata;) *src++ = *dst++;
// Call main()
extern void main(void);
main();
for (;;) (void) 0;
}
void __attribute__((weak)) DefaultIRQHandler(void) {
for (;;) (void) 0;
}
#define WEAK_ALIAS __attribute__((weak, alias("DefaultIRQHandler")))
WEAK_ALIAS void NMI_Handler(void);
WEAK_ALIAS void HardFault_Handler(void);
WEAK_ALIAS void MemManage_Handler(void);
WEAK_ALIAS void BusFault_Handler(void);
WEAK_ALIAS void UsageFault_Handler(void);
WEAK_ALIAS void SVC_Handler(void);
WEAK_ALIAS void DebugMon_Handler(void);
WEAK_ALIAS void PendSV_Handler(void);
WEAK_ALIAS void SysTick_Handler(void);
WEAK_ALIAS void WWDG_IRQHandler(void);
WEAK_ALIAS void PVD_IRQHandler(void);
WEAK_ALIAS void TAMP_STAMP_IRQHandler(void);
WEAK_ALIAS void RTC_WKUP_IRQHandler(void);
WEAK_ALIAS void FLASH_IRQHandler(void);
WEAK_ALIAS void RCC_IRQHandler(void);
WEAK_ALIAS void EXTI0_IRQHandler(void);
WEAK_ALIAS void EXTI1_IRQHandler(void);
WEAK_ALIAS void EXTI2_IRQHandler(void);
WEAK_ALIAS void EXTI3_IRQHandler(void);
WEAK_ALIAS void EXTI4_IRQHandler(void);
WEAK_ALIAS void EXTI9_5_IRQHandler(void);
WEAK_ALIAS void EXTI15_10_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream0_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream1_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream2_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream3_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream4_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream5_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream6_IRQHandler(void);
WEAK_ALIAS void ADC_IRQHandler(void);
WEAK_ALIAS void CAN1_TX_IRQHandler(void);
WEAK_ALIAS void CAN1_RX0_IRQHandler(void);
WEAK_ALIAS void CAN1_RX1_IRQHandler(void);
WEAK_ALIAS void CAN1_SCE_IRQHandler(void);
WEAK_ALIAS void TIM1_BRK_TIM9_IRQHandler(void);
WEAK_ALIAS void TIM1_UP_TIM10_IRQHandler(void);
WEAK_ALIAS void TIM1_TRG_COM_TIM11_IRQHandler(void);
WEAK_ALIAS void TIM1_CC_IRQHandler(void);
WEAK_ALIAS void TIM2_IRQHandler(void);
WEAK_ALIAS void TIM3_IRQHandler(void);
WEAK_ALIAS void TIM4_IRQHandler(void);
WEAK_ALIAS void I2C1_EV_IRQHandler(void);
WEAK_ALIAS void I2C1_ER_IRQHandler(void);
WEAK_ALIAS void I2C2_EV_IRQHandler(void);
WEAK_ALIAS void I2C2_ER_IRQHandler(void);
WEAK_ALIAS void SPI1_IRQHandler(void);
WEAK_ALIAS void SPI2_IRQHandler(void);
WEAK_ALIAS void USART1_IRQHandler(void);
WEAK_ALIAS void USART2_IRQHandler(void);
WEAK_ALIAS void USART3_IRQHandler(void);
WEAK_ALIAS void RTC_Alarm_IRQHandler(void);
WEAK_ALIAS void OTG_FS_WKUP_IRQHandler(void);
WEAK_ALIAS void TIM8_BRK_TIM12_IRQHandler(void);
WEAK_ALIAS void TIM8_UP_TIM13_IRQHandler(void);
WEAK_ALIAS void TIM8_TRG_COM_TIM14_IRQHandler(void);
WEAK_ALIAS void TIM8_CC_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream7_IRQHandler(void);
WEAK_ALIAS void FMC_IRQHandler(void);
WEAK_ALIAS void SDMMC1_IRQHandler(void);
WEAK_ALIAS void TIM5_IRQHandler(void);
WEAK_ALIAS void SPI3_IRQHandler(void);
WEAK_ALIAS void UART4_IRQHandler(void);
WEAK_ALIAS void UART5_IRQHandler(void);
WEAK_ALIAS void TIM6_DAC_IRQHandler(void);
WEAK_ALIAS void TIM7_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream0_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream1_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream2_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream3_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream4_IRQHandler(void);
WEAK_ALIAS void ETH_IRQHandler(void);
WEAK_ALIAS void ETH_WKUP_IRQHandler(void);
WEAK_ALIAS void CAN2_TX_IRQHandler(void);
WEAK_ALIAS void CAN2_RX0_IRQHandler(void);
WEAK_ALIAS void CAN2_RX1_IRQHandler(void);
WEAK_ALIAS void CAN2_SCE_IRQHandler(void);
WEAK_ALIAS void OTG_FS_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream5_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream6_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream7_IRQHandler(void);
WEAK_ALIAS void USART6_IRQHandler(void);
WEAK_ALIAS void I2C3_EV_IRQHandler(void);
WEAK_ALIAS void I2C3_ER_IRQHandler(void);
WEAK_ALIAS void OTG_HS_EP1_OUT_IRQHandler(void);
WEAK_ALIAS void OTG_HS_EP1_IN_IRQHandler(void);
WEAK_ALIAS void OTG_HS_WKUP_IRQHandler(void);
WEAK_ALIAS void OTG_HS_IRQHandler(void);
WEAK_ALIAS void DCMI_IRQHandler(void);
WEAK_ALIAS void RNG_IRQHandler(void);
WEAK_ALIAS void FPU_IRQHandler(void);
WEAK_ALIAS void UART7_IRQHandler(void);
WEAK_ALIAS void UART8_IRQHandler(void);
WEAK_ALIAS void SPI4_IRQHandler(void);
WEAK_ALIAS void SPI5_IRQHandler(void);
WEAK_ALIAS void SPI6_IRQHandler(void);
WEAK_ALIAS void SAI1_IRQHandler(void);
WEAK_ALIAS void LTDC_IRQHandler(void);
WEAK_ALIAS void LTDC_ER_IRQHandler(void);
WEAK_ALIAS void DMA2D_IRQHandler(void);
// IRQ table
extern void _estack();
__attribute__((section(".vectors"))) void (*tab[16 + 91])(void) = {
// Cortex interrupts
_estack, _reset, NMI_Handler, HardFault_Handler, MemManage_Handler,
BusFault_Handler, UsageFault_Handler, 0, 0, 0, 0, SVC_Handler,
DebugMon_Handler, 0, PendSV_Handler, SysTick_Handler,
// Interrupts from peripherals
WWDG_IRQHandler, PVD_IRQHandler, TAMP_STAMP_IRQHandler, RTC_WKUP_IRQHandler,
FLASH_IRQHandler, RCC_IRQHandler, EXTI0_IRQHandler, EXTI1_IRQHandler,
EXTI2_IRQHandler, EXTI3_IRQHandler, EXTI4_IRQHandler,
DMA1_Stream0_IRQHandler, DMA1_Stream1_IRQHandler, DMA1_Stream2_IRQHandler,
DMA1_Stream3_IRQHandler, DMA1_Stream4_IRQHandler, DMA1_Stream5_IRQHandler,
DMA1_Stream6_IRQHandler, ADC_IRQHandler, CAN1_TX_IRQHandler,
CAN1_RX0_IRQHandler, CAN1_RX1_IRQHandler, CAN1_SCE_IRQHandler,
EXTI9_5_IRQHandler, TIM1_BRK_TIM9_IRQHandler, TIM1_UP_TIM10_IRQHandler,
TIM1_TRG_COM_TIM11_IRQHandler, TIM1_CC_IRQHandler, TIM2_IRQHandler,
TIM3_IRQHandler, TIM4_IRQHandler, I2C1_EV_IRQHandler, I2C1_ER_IRQHandler,
I2C2_EV_IRQHandler, I2C2_ER_IRQHandler, SPI1_IRQHandler, SPI2_IRQHandler,
USART1_IRQHandler, USART2_IRQHandler, USART3_IRQHandler,
EXTI15_10_IRQHandler, RTC_Alarm_IRQHandler, OTG_FS_WKUP_IRQHandler,
TIM8_BRK_TIM12_IRQHandler, TIM8_UP_TIM13_IRQHandler,
TIM8_TRG_COM_TIM14_IRQHandler, TIM8_CC_IRQHandler, DMA1_Stream7_IRQHandler,
FMC_IRQHandler, SDMMC1_IRQHandler, TIM5_IRQHandler, SPI3_IRQHandler,
UART4_IRQHandler, UART5_IRQHandler, TIM6_DAC_IRQHandler, TIM7_IRQHandler,
DMA2_Stream0_IRQHandler, DMA2_Stream1_IRQHandler, DMA2_Stream2_IRQHandler,
DMA2_Stream3_IRQHandler, DMA2_Stream4_IRQHandler, ETH_IRQHandler,
ETH_WKUP_IRQHandler, CAN2_TX_IRQHandler, CAN2_RX0_IRQHandler,
CAN2_RX1_IRQHandler, CAN2_SCE_IRQHandler, OTG_FS_IRQHandler,
DMA2_Stream5_IRQHandler, DMA2_Stream6_IRQHandler, DMA2_Stream7_IRQHandler,
USART6_IRQHandler, I2C3_EV_IRQHandler, I2C3_ER_IRQHandler,
OTG_HS_EP1_OUT_IRQHandler, OTG_HS_EP1_IN_IRQHandler, OTG_HS_WKUP_IRQHandler,
OTG_HS_IRQHandler, DCMI_IRQHandler, 0, RNG_IRQHandler, FPU_IRQHandler,
UART7_IRQHandler, UART8_IRQHandler, SPI4_IRQHandler, SPI5_IRQHandler,
SPI6_IRQHandler, SAI1_IRQHandler, LTDC_IRQHandler, LTDC_ER_IRQHandler,
DMA2D_IRQHandler};
@@ -0,0 +1,29 @@
ENTRY(_reset);
MEMORY {
flash(rx) : ORIGIN = 0x08000000, LENGTH = 2048k
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 192k /* remaining 64k in a separate address space */
}
_estack = ORIGIN(sram) + LENGTH(sram); /* stack points to end of SRAM */
SECTIONS {
.vectors : { KEEP(*(.vectors)) } > flash
.text : { *(.text*) } > flash
.rodata : { *(.rodata*) } > flash
.data : {
_sdata = .; /* for init_ram() */
*(.first_data)
*(.data SORT(.data.*))
_edata = .; /* for init_ram() */
} > sram AT > flash
_sidata = LOADADDR(.data);
.bss : {
_sbss = .; /* for init_ram() */
*(.bss SORT(.bss.*) COMMON)
_ebss = .; /* for init_ram() */
} > sram
. = ALIGN(8);
_end = .; /* for cmsis_gcc.h and init_ram() */
}
@@ -0,0 +1,96 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mcu.h"
#include "mongoose.h"
#define LED1 PIN('B', 0) // On-board LED pin (green)
#define LED2 PIN('B', 7) // On-board LED pin (blue)
#define LED3 PIN('B', 14) // On-board LED pin (red)
#define BTN1 PIN('C', 13) // On-board user button
#define BLINK_PERIOD_MS 1000 // LED blinking period in millis
static uint64_t s_ticks, s_exti; // Counters, increased by IRQ handlers
uint64_t mg_millis(void) { // Declare our own uptime function
return s_ticks; // Return number of milliseconds since boot
}
void HardFault_Handler(void) { // Escalated fault handler
gpio_output(LED3); // Setup red LED
for (;;) spin(2999999), gpio_toggle(LED3); // Blink LED infinitely
}
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
s_ticks++;
}
void EXTI15_10_IRQHandler(void) { // External interrupt handler
s_exti++;
if (EXTI->PR & BIT(PINNO(BTN1))) EXTI->PR = BIT(PINNO(BTN1));
gpio_write(LED1, gpio_read(BTN1)); // No debounce. Turn LED if button pressed
}
static void timer_cb(void *arg) {
gpio_toggle(LED2); // Blink LED
bool up = ((struct mip_if *) arg)->state == MIP_STATE_READY;
MG_INFO(("Ethernet: %s", up ? "up" : "down")); // Show network status
}
int main(void) {
clock_init(); // Set clock to 180MHz
systick_init(SYS_FREQUENCY / 1000); // Increment s_ticks every ms
gpio_output(LED1); // Setup green LED
gpio_output(LED2); // Setup blue LED
gpio_input(BTN1); // Set button to input
irq_exti_attach(BTN1); // Attach BTN1 to exti
uart_init(UART1, 115200); // Initialise debug printf
MG_INFO(("Starting, CPU freq %g MHz", (double) SYS_FREQUENCY / 1000000));
// Initialise Ethernet. Enable MAC GPIO pins, see
// https://www.farnell.com/datasheets/2014265.pdf section 6.10
uint16_t pins[] = {PIN('A', 1), PIN('A', 2), PIN('A', 7),
PIN('B', 13), PIN('C', 1), PIN('C', 4),
PIN('C', 5), PIN('G', 11), PIN('G', 13)};
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
gpio_init(pins[i], GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_INSANE,
GPIO_PULL_NONE, 11);
}
nvic_enable_irq(61); // Setup Ethernet IRQ handler
RCC->APB2ENR |= BIT(14); // Enable SYSCFG
SYSCFG->PMC |= BIT(23); // Use RMII. Goes first!
RCC->AHB1ENR |= BIT(25) | BIT(26) | BIT(27); // Enable Ethernet clocks
RCC->AHB1RSTR |= BIT(25); // ETHMAC force reset
RCC->AHB1RSTR &= ~BIT(25); // ETHMAC release reset
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the MIP interface
mg_log_set(MG_LL_DEBUG); // Set log level
// Initialise Mongoose network stack
// Specify MAC address, and IP/mask/GW in network byte order for static
// IP configuration. If IP/mask/GW are unset, DHCP is going to be used
struct mip_driver_stm32_data driver_data = {.mdc_cr = 4}; // driver_stm32.h
struct mip_if mif = {.mac = {2, 0, 1, 2, 3, 5},
.driver = &mip_driver_stm32,
.driver_data = &driver_data};
mip_init(&mgr, &mif);
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_cb, &mif);
MG_INFO(("Waiting until network is up..."));
while (mif.state != MIP_STATE_READY) {
mg_mgr_poll(&mgr, 0);
}
MG_INFO(("Initialising application..."));
extern void device_dashboard_fn(struct mg_connection *, int, void *, void *);
mg_http_listen(&mgr, "http://0.0.0.0", device_dashboard_fn, &mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -0,0 +1,208 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
// https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define BIT(x) (1UL << (x))
#define SETBITS(R, CLEARMASK, SETMASK) (R) = ((R) & ~(CLEARMASK)) | (SETMASK)
#define PIN(bank, num) ((((bank) - 'A') << 8) | (num))
#define PINNO(pin) (pin & 255)
#define PINBANK(pin) (pin >> 8)
// 6.3.3: APB1 clock <= 45MHz; APB2 clock <= 90MHz
// 3.5.1, Table 11: configure flash latency (WS) in accordance to clock freq
// 33.4: The AHB clock must be at least 25 MHz when Ethernet is used
enum { APB1_PRE = 5 /* AHB clock / 4 */, APB2_PRE = 4 /* AHB clock / 2 */ };
enum { PLL_HSI = 16, PLL_M = 8, PLL_N = 180, PLL_P = 2 }; // Run at 180 Mhz
#define FLASH_LATENCY 5
#define SYS_FREQUENCY ((PLL_HSI * PLL_N / PLL_M / PLL_P) * 1000000)
#define APB2_FREQUENCY (SYS_FREQUENCY / (BIT(APB2_PRE - 3)))
#define APB1_FREQUENCY (SYS_FREQUENCY / (BIT(APB1_PRE - 3)))
static inline void spin(volatile uint32_t count) {
while (count--) asm("nop");
}
struct rcc {
volatile uint32_t CR, PLLCFGR, CFGR, CIR, AHB1RSTR, AHB2RSTR, AHB3RSTR,
RESERVED0, APB1RSTR, APB2RSTR, RESERVED1[2], AHB1ENR, AHB2ENR, AHB3ENR,
RESERVED2, APB1ENR, APB2ENR, RESERVED3[2], AHB1LPENR, AHB2LPENR,
AHB3LPENR, RESERVED4, APB1LPENR, APB2LPENR, RESERVED5[2], BDCR, CSR,
RESERVED6[2], SSCGR, PLLI2SCFGR;
};
#define RCC ((struct rcc *) 0x40023800)
struct pwr {
volatile uint32_t CR, CSR;
};
#define PWR ((struct pwr *) 0x40007000)
struct nvic {
volatile uint32_t ISER[8], RESERVED0[24], ICER[8], RSERVED1[24], ISPR[8],
RESERVED2[24], ICPR[8], RESERVED3[24], IABR[8], RESERVED4[56], IP[240],
RESERVED5[644], STIR;
};
#define NVIC ((struct nvic *) 0xe000e100)
static inline void nvic_set_prio(int irq, uint32_t prio) {
NVIC->IP[irq] = prio << 4;
}
static inline void nvic_enable_irq(int irq) {
NVIC->ISER[irq >> 5] = (uint32_t) (1 << (irq & 31));
}
struct systick {
volatile uint32_t CTRL, LOAD, VAL, CALIB;
};
#define SYSTICK ((struct systick *) 0xe000e010) // 2.2.2
static inline void systick_init(uint32_t ticks) {
if ((ticks - 1) > 0xffffff) return; // Systick timer is 24 bit
SYSTICK->LOAD = ticks - 1;
SYSTICK->VAL = 0;
SYSTICK->CTRL = BIT(0) | BIT(1) | BIT(2); // Enable systick
}
struct flash {
volatile uint32_t ACR, KEYR, OPTKEYR, SR, CR, AR, RESERVED, OBR, WRPR;
};
#define FLASH ((struct flash *) 0x40023c00)
struct scb {
volatile uint32_t CPUID, ICSR, VTOR, AIRCR, SCR, CCR, SHPR[3], SHCSR, CFSR,
HFSR, DFSR, MMFAR, BFAR, AFSR, ID_PFR[2], ID_DFR, ID_AFR, ID_MFR[4],
ID_ISAR[5], RESERVED0[1], CLIDR, CTR, CCSIDR, CSSELR, CPACR,
RESERVED3[93], STIR, RESERVED4[15], MVFR0, MVFR1, MVFR2, RESERVED5[1],
ICIALLU, RESERVED6[1], ICIMVAU, DCIMVAC, DCISW, DCCMVAU, DCCMVAC, DCCSW,
DCCIMVAC, DCCISW, RESERVED7[6], ITCMCR, DTCMCR, AHBPCR, CACR, AHBSCR,
RESERVED8[1], ABFSR;
};
#define SCB ((struct scb *) 0xe000ed00)
enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG };
enum { GPIO_OTYPE_PUSH_PULL, GPIO_OTYPE_OPEN_DRAIN };
enum { GPIO_SPEED_LOW, GPIO_SPEED_MEDIUM, GPIO_SPEED_HIGH, GPIO_SPEED_INSANE };
enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN };
struct gpio {
volatile uint32_t MODER, OTYPER, OSPEEDR, PUPDR, IDR, ODR, BSRR, LCKR, AFR[2];
};
#define GPIO(N) ((struct gpio *) (0x40020000 + 0x400 * (N)))
static struct gpio *gpio_bank(uint16_t pin) { return GPIO(PINBANK(pin)); }
static inline void gpio_toggle(uint16_t pin) {
struct gpio *gpio = gpio_bank(pin);
uint32_t mask = BIT(PINNO(pin));
gpio->BSRR = mask << (gpio->ODR & mask ? 16 : 0);
}
static inline int gpio_read(uint16_t pin) {
return gpio_bank(pin)->IDR & BIT(PINNO(pin)) ? 1 : 0;
}
static inline void gpio_write(uint16_t pin, bool val) {
struct gpio *gpio = gpio_bank(pin);
gpio->BSRR = BIT(PINNO(pin)) << (val ? 0 : 16);
}
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
uint8_t speed, uint8_t pull, uint8_t af) {
struct gpio *gpio = gpio_bank(pin);
uint8_t n = (uint8_t) (PINNO(pin));
RCC->AHB1ENR |= BIT(PINBANK(pin)); // Enable GPIO clock
SETBITS(gpio->OTYPER, 1UL << n, ((uint32_t) type) << n);
SETBITS(gpio->OSPEEDR, 3UL << (n * 2), ((uint32_t) speed) << (n * 2));
SETBITS(gpio->PUPDR, 3UL << (n * 2), ((uint32_t) pull) << (n * 2));
SETBITS(gpio->AFR[n >> 3], 15UL << ((n & 7) * 4),
((uint32_t) af) << ((n & 7) * 4));
SETBITS(gpio->MODER, 3UL << (n * 2), ((uint32_t) mode) << (n * 2));
}
static inline void gpio_input(uint16_t pin) {
gpio_init(pin, GPIO_MODE_INPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH,
GPIO_PULL_NONE, 0);
}
static inline void gpio_output(uint16_t pin) {
gpio_init(pin, GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH,
GPIO_PULL_NONE, 0);
}
struct syscfg {
volatile uint32_t MEMRMP, PMC, EXTICR[4], RESERVED[2], CMPCR;
};
#define SYSCFG ((struct syscfg *) 0x40013800)
struct exti {
volatile uint32_t IMR, EMR, RTSR, FTSR, SWIER, PR;
};
#define EXTI ((struct exti *) 0x40013c00)
static inline void irq_exti_attach(uint16_t pin) {
uint8_t bank = (uint8_t) (PINBANK(pin)), n = (uint8_t) (PINNO(pin));
RCC->APB2ENR |= BIT(14); // Enable SYSCFG
SYSCFG->EXTICR[n / 4] &= ~(15UL << ((n % 4) * 4));
SYSCFG->EXTICR[n / 4] |= (uint32_t) (bank << ((n % 4) * 4));
EXTI->IMR |= BIT(n);
EXTI->RTSR |= BIT(n);
EXTI->FTSR |= BIT(n);
int irqvec = n < 5 ? 6 + n : n < 10 ? 23 : 40; // IRQ vector index, 10.1.2
nvic_set_prio(irqvec, 3);
nvic_enable_irq(irqvec);
}
struct uart {
volatile uint32_t SR, DR, BRR, CR1, CR2, CR3, GTPR;
};
#define UART1 ((struct uart *) 0x40011000)
#define UART2 ((struct uart *) 0x40004400)
#define UART3 ((struct uart *) 0x40004800)
static inline void uart_init(struct uart *uart, unsigned long baud) {
// https://www.st.com/resource/en/datasheet/stm32f429zi.pdf
uint8_t af = 7; // Alternate function
uint16_t rx = 0, tx = 0; // pins
uint32_t freq = 0; // Bus frequency. UART1 is on APB2, rest on APB1
if (uart == UART1) freq = APB2_FREQUENCY, RCC->APB2ENR |= BIT(4);
if (uart == UART2) freq = APB1_FREQUENCY, RCC->APB1ENR |= BIT(17);
if (uart == UART3) freq = APB1_FREQUENCY, RCC->APB1ENR |= BIT(18);
if (uart == UART1) tx = PIN('A', 9), rx = PIN('A', 10);
if (uart == UART2) tx = PIN('A', 2), rx = PIN('A', 3);
if (uart == UART3) tx = PIN('D', 8), rx = PIN('D', 9);
gpio_init(tx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af);
gpio_init(rx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af);
uart->CR1 = 0; // Disable this UART
uart->BRR = freq / baud; // Set baud rate
uart->CR1 |= BIT(13) | BIT(2) | BIT(3); // Set UE, RE, TE
}
static inline void uart_write_byte(struct uart *uart, uint8_t byte) {
uart->DR = byte;
while ((uart->SR & BIT(7)) == 0) spin(1);
}
static inline void uart_write_buf(struct uart *uart, char *buf, size_t len) {
while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++);
}
static inline int uart_read_ready(struct uart *uart) {
return uart->SR & BIT(5); // If RXNE bit is set, data is ready
}
static inline uint8_t uart_read_byte(struct uart *uart) {
return (uint8_t) (uart->DR & 255);
}
static inline void clock_init(void) { // Set clock frequency
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
asm("DSB");
asm("ISB");
FLASH->ACR |= FLASH_LATENCY | BIT(8) |
BIT(9); // Flash latency, prefetch, Icache, Dcache
RCC->PLLCFGR &= ~((BIT(17) - 1)); // Clear PLL multipliers
RCC->PLLCFGR |= (((PLL_P - 2) / 2) & 3) << 16; // Set PLL_P
RCC->PLLCFGR |= PLL_M | (PLL_N << 6); // Set PLL_M and PLL_N
RCC->CR |= BIT(24); // Enable PLL
while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done
RCC->CFGR = (APB1_PRE << 10) | (APB2_PRE << 13); // Set prescalers
RCC->CFGR |= 2; // Set clock source to PLL
while ((RCC->CFGR & 12) == 0) spin(1); // Wait until done
}
@@ -0,0 +1,83 @@
#include <sys/stat.h>
#include "mcu.h"
int _fstat(int fd, struct stat *st) {
if (fd < 0) return -1;
st->st_mode = S_IFCHR;
return 0;
}
void *_sbrk(int incr) {
extern char _end;
static unsigned char *heap = NULL;
unsigned char *prev_heap;
if (heap == NULL) heap = (unsigned char *) &_end;
prev_heap = heap;
heap += incr;
return prev_heap;
}
int _open(const char *path) {
(void) path;
return -1;
}
int _close(int fd) {
(void) fd;
return -1;
}
int _isatty(int fd) {
(void) fd;
return 1;
}
int _lseek(int fd, int ptr, int dir) {
(void) fd, (void) ptr, (void) dir;
return 0;
}
void _exit(int status) {
(void) status;
for (;;) asm volatile("BKPT #0");
}
void _kill(int pid, int sig) {
(void) pid, (void) sig;
}
int _getpid(void) {
return -1;
}
int _write(int fd, char *ptr, int len) {
(void) fd, (void) ptr, (void) len;
if (fd == 1) uart_write_buf(UART1, ptr, (size_t) len);
return -1;
}
int _read(int fd, char *ptr, int len) {
(void) fd, (void) ptr, (void) len;
return -1;
}
int _link(const char *a, const char *b) {
(void) a, (void) b;
return -1;
}
int _unlink(const char *a) {
(void) a;
return -1;
}
int _stat(const char *path, struct stat *st) {
(void) path, (void) st;
return -1;
}
int mkdir(const char *path, mode_t mode) {
(void) path, (void) mode;
return -1;
}
@@ -0,0 +1,37 @@
#pragma once
#include "mcu.h"
#define configUSE_PREEMPTION 1
#define configCPU_CLOCK_HZ SYS_FREQUENCY
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES 5
#define configUSE_16_BIT_TICKS 0
#define configUSE_TICK_HOOK 0
#define configUSE_IDLE_HOOK 0
#define configUSE_TIMERS 0
#define configUSE_CO_ROUTINES 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configMINIMAL_STACK_SIZE 128
#define configTOTAL_HEAP_SIZE (1024 * 98)
#define INCLUDE_vTaskDelay 1
#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 5
#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 configASSERT(expr) \
if (!(expr)) printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr)
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
@@ -0,0 +1,34 @@
CFLAGS ?= -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion \
-Wformat-truncation -fno-common -Wconversion \
-g3 -Os -ffunction-sections -fdata-sections \
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-I. -Icmsis -I../../../ $(EXTRA_CFLAGS)
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = main.c startup.c syscalls.c ../../../mongoose.c
FREERTOS_VERSION ?= V10.5.0
FREERTOS_REPO ?= https://github.com/FreeRTOS/FreeRTOS-Kernel
build example: firmware.bin
firmware.elf: FreeRTOS-Kernel $(SOURCES)
arm-none-eabi-gcc -o $@ $(SOURCES) $(CFLAGS) \
-IFreeRTOS-Kernel/include \
-IFreeRTOS-Kernel/portable/GCC/ARM_CM4F \
-Wno-conversion \
$(wildcard FreeRTOS-Kernel/*.c) \
FreeRTOS-Kernel/portable/MemMang/heap_4.c \
FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c \
$(LDFLAGS)
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
flash: firmware.bin
st-flash --reset write firmware.bin 0x8000000
FreeRTOS-Kernel:
git clone --depth 1 -b $(FREERTOS_VERSION) $(FREERTOS_REPO) $@
clean:
rm -rf firmware.* FreeRTOS-Kernel
@@ -0,0 +1,39 @@
# MIP webserver over FreeRTOS on NUCLEO-F429ZI
This firmware uses MIP, an experimental TCP/IP stack of the Mongoose Network Library, running as a FreeRTOS task.
It implements the following:
- Minimal elementary web server, as simple as possible
- Interrupt-driven [Ethernet driver](../../../drivers/mip_driver_stm32.c)
- Basic HAL header [mcu.h](mcu.h) based on CMSIS
- Blue LED blinky, based on another FreeRTOS task
- Debug log on UART3 (st-link)
## Requirements
- [GNU make](http://mongoose.ws/tutorials/tools/#gnu-make)
- [ARM GCC](http://mongoose.ws/tutorials/tools/#arm-gcc)
- [stlink](http://mongoose.ws/tutorials/tools/#stlink) for flashing
The links above will send you to tutorials on how to install each of those tools in your workstation for Linux, Mac, and Windows.
You'll also need _git_ so the Makefile can clone the FreeRTOS-Kernel repository. We assume you have it since you got to get this repository somehow. If you don't, and don't want to install it, just get the proper [FreeRTOS-Kernel](https://github.com/FreeRTOS/FreeRTOS-Kernel) version (see the Makefile) from its repository, as you did with the Mongoose repository.
## Usage
Plugin your Nucleo board into USB, and attach an Ethernet cable.
To build and flash:
```sh
$ make clean flash
```
To see debug log, use any serial monitor program like `picocom` at 115200 bps and configure it to insert carriage returns after line feeds:
```sh
$ picocom /dev/ttyACM0 -i -b 115200 --imap=lfcrlf
```
There is also a [detailed tutorial on this example](http://mongoose.ws/tutorials/stm32/nucleo-f429zi-freertos-mip/)
For more details and benchmark data on MIP, check the [F746ZG example](../nucleo-f746zg-baremetal/)
@@ -0,0 +1,266 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.0.4
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/*
* 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.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,39 @@
/**************************************************************************//**
* @file cmsis_version.h
* @brief CMSIS Core(M) Version definitions
* @version V5.0.2
* @date 19. April 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CMSIS_VERSION_H
#define __CMSIS_VERSION_H
/* CMSIS Version definitions */
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
#endif
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,270 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for Armv7-M MPU
* @version V5.0.4
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2017-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_MPU_ARMV7_H
#define ARM_MPU_ARMV7_H
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) \
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
((Region) & MPU_RBAR_REGION_Msk) | \
(MPU_RBAR_VALID_Msk))
/**
* MPU Memory Access Attributes
*
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
*/
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
((((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) ) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk)))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
/**
* MPU Memory Access Attribute for strongly ordered memory.
* - TEX: 000b
* - Shareable
* - Non-cacheable
* - Non-bufferable
*/
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
/**
* MPU Memory Access Attribute for device memory.
* - TEX: 000b (if non-shareable) or 010b (if shareable)
* - Shareable or non-shareable
* - Non-cacheable
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
*
* \param IsShareable Configures the device memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
/**
* MPU Memory Access Attribute for normal memory.
* - TEX: 1BBb (reflecting outer cacheability rules)
* - Shareable or non-shareable
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
*
* \param OuterCp Configures the outer cache policy.
* \param InnerCp Configures the inner cache policy.
* \param IsShareable Configures the memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U))
/**
* MPU Memory Access Attribute non-cacheable policy.
*/
#define ARM_MPU_CACHEP_NOCACHE 0U
/**
* MPU Memory Access Attribute write-back, write and read allocate policy.
*/
#define ARM_MPU_CACHEP_WB_WRA 1U
/**
* MPU Memory Access Attribute write-through, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WT_NWA 2U
/**
* MPU Memory Access Attribute write-back, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WB_NWA 3U
/**
* Struct for a single MPU Region
*/
typedef struct {
uint32_t RBAR; //!< The region base address register value (RBAR)
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DSB();
__ISB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable(void)
{
__DSB();
__ISB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
MPU->RNR = rnr;
MPU->RASR = 0U;
}
/** Configure an MPU region.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
{
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
{
MPU->RNR = rnr;
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Memcopy with strictly ordered memory access, e.g. for register targets.
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0U; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
{
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
while (cnt > MPU_TYPE_RALIASES) {
orderedCpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
table += MPU_TYPE_RALIASES;
cnt -= MPU_TYPE_RALIASES;
}
orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
}
#endif
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,104 @@
/**
******************************************************************************
* @file system_stm32f4xx.h
* @author MCD Application Team
* @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices.
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f4xx_system
* @{
*/
/**
* @brief Define to prevent recursive inclusion
*/
#ifndef __SYSTEM_STM32F4XX_H
#define __SYSTEM_STM32F4XX_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup STM32F4xx_System_Includes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_types
* @{
*/
/* This 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 STM32F4xx_System_Exported_Constants
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Exported_Functions
* @{
*/
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__SYSTEM_STM32F4XX_H */
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,29 @@
ENTRY(_reset);
MEMORY {
flash(rx) : ORIGIN = 0x08000000, LENGTH = 2048k
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 192k /* remaining 64k in a separate address space */
}
_estack = ORIGIN(sram) + LENGTH(sram); /* stack points to end of SRAM */
SECTIONS {
.vectors : { KEEP(*(.vectors)) } > flash
.text : { *(.text*) } > flash
.rodata : { *(.rodata*) } > flash
.data : {
_sdata = .; /* .data section start */
*(.first_data)
*(.data SORT(.data.*))
_edata = .; /* .data section end */
} > sram AT > flash
_sidata = LOADADDR(.data);
.bss : {
_sbss = .; /* .bss section start */
*(.bss SORT(.bss.*) COMMON)
_ebss = .; /* .bss section end */
} > sram
. = ALIGN(8);
_end = .; /* for cmsis_gcc.h */
}
@@ -0,0 +1,84 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mcu.h"
#include "mongoose.h"
// HTTP server event handler function
static void fn(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;
if (mg_http_match_uri(hm, "/api/debug")) {
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
mg_log_set(level);
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
} else {
mg_http_reply(c, 200, "", "%s\n", "hi");
}
}
(void) fn_data;
}
static void ethernet_init(void) {
// Initialise Ethernet. Enable MAC GPIO pins, see
// https://www.farnell.com/datasheets/2014265.pdf section 6.10
uint16_t pins[] = {PIN('A', 1), PIN('A', 2), PIN('A', 7),
PIN('B', 13), PIN('C', 1), PIN('C', 4),
PIN('C', 5), PIN('G', 11), PIN('G', 13)};
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
gpio_init(pins[i], GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_INSANE,
GPIO_PULL_NONE, 11);
}
NVIC_EnableIRQ(61); // Setup Ethernet IRQ handler
RCC->APB2ENR |= BIT(14); // Enable SYSCFG
SYSCFG->PMC |= BIT(23); // Use RMII. Goes first!
RCC->AHB1ENR |= BIT(25) | BIT(26) | BIT(27); // Enable Ethernet clocks
RCC->AHB1RSTR |= BIT(25); // ETHMAC force reset
RCC->AHB1RSTR &= ~BIT(25); // ETHMAC release reset
}
static void server(void *args) {
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the MIP interface
mg_log_set(MG_LL_DEBUG); // Set log level
// Initialise Mongoose network stack
// Specify MAC address, and IP/mask/GW in network byte order for static
// IP configuration. If IP/mask/GW are unset, DHCP is going to be used
MG_INFO(("Initializing Ethernet driver"));
ethernet_init();
struct mip_driver_stm32_data driver_data = {.mdc_cr = 4}; // See driver_stm32.h
struct mip_if mif = {
.mac = {2, 0, 1, 2, 3, 5},
.driver = &mip_driver_stm32,
.driver_data = &driver_data,
};
mip_init(&mgr, &mif);
MG_INFO(("Starting Mongoose v%s", MG_VERSION)); // Tell the world
mg_http_listen(&mgr, "http://0.0.0.0", fn, &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 led = PIN('B', 7);
gpio_init(led, GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_MEDIUM,
GPIO_PULL_NONE, 0);
for (;;) {
gpio_toggle(led);
vTaskDelay(pdMS_TO_TICKS(750));
MG_INFO(("blink %s, RAM: %u", (char *) args, xPortGetFreeHeapSize()));
}
}
int main(void) {
clock_init(); // Set clock to max of 180 MHz
systick_init(SYS_FREQUENCY / 1000); // Tick every 1 ms
uart_init(UART3, 115200); // Initialise UART
xTaskCreate(blinker, "blinker", 128, ":)", configMAX_PRIORITIES - 1, NULL);
xTaskCreate(server, "server", 2048, 0, configMAX_PRIORITIES - 1, NULL);
vTaskStartScheduler(); // This blocks
return 0;
}
@@ -0,0 +1,154 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
// https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
#pragma once
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "stm32f429xx.h"
#define BIT(x) (1UL << (x))
#define SETBITS(R, CLEARMASK, SETMASK) (R) = ((R) & ~(CLEARMASK)) | (SETMASK)
#define PIN(bank, num) ((((bank) - 'A') << 8) | (num))
#define PINNO(pin) (pin & 255)
#define PINBANK(pin) (pin >> 8)
// 6.3.3: APB1 clock <= 45MHz; APB2 clock <= 90MHz
// 3.5.1, Table 11: configure flash latency (WS) in accordance to clock freq
// 33.4: The AHB clock must be at least 25 MHz when Ethernet is used
enum { APB1_PRE = 5 /* AHB clock / 4 */, APB2_PRE = 4 /* AHB clock / 2 */ };
enum { PLL_HSI = 16, PLL_M = 8, PLL_N = 180, PLL_P = 2 }; // Run at 180 Mhz
#define FLASH_LATENCY 5
#define SYS_FREQUENCY ((PLL_HSI * PLL_N / PLL_M / PLL_P) * 1000000)
#define APB2_FREQUENCY (SYS_FREQUENCY / (BIT(APB2_PRE - 3)))
#define APB1_FREQUENCY (SYS_FREQUENCY / (BIT(APB1_PRE - 3)))
static inline void spin(volatile uint32_t count) {
while (count--) asm("nop");
}
static inline void systick_init(uint32_t ticks) {
if ((ticks - 1) > 0xffffff) return; // Systick timer is 24 bit
SysTick->LOAD = ticks - 1;
SysTick->VAL = 0;
SysTick->CTRL = BIT(0) | BIT(1) | BIT(2); // Enable systick
}
#define GPIO(bank) ((GPIO_TypeDef *) (GPIOA_BASE + 0x400 * (bank)))
enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG };
enum { GPIO_OTYPE_PUSH_PULL, GPIO_OTYPE_OPEN_DRAIN };
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(PINBANK(pin)); // GPIO bank
uint8_t n = (uint8_t) (PINNO(pin));
RCC->AHB1ENR |= BIT(PINBANK(pin)); // Enable GPIO clock
SETBITS(gpio->OTYPER, 1UL << n, ((uint32_t) type) << n);
SETBITS(gpio->OSPEEDR, 3UL << (n * 2), ((uint32_t) speed) << (n * 2));
SETBITS(gpio->PUPDR, 3UL << (n * 2), ((uint32_t) pull) << (n * 2));
SETBITS(gpio->AFR[n >> 3], 15UL << ((n & 7) * 4),
((uint32_t) af) << ((n & 7) * 4));
SETBITS(gpio->MODER, 3UL << (n * 2), ((uint32_t) mode) << (n * 2));
}
#if 0
static inline void gpio_set_mode(uint16_t pin, uint8_t mode) {
GPIO_TypeDef *gpio = GPIO(PINBANK(pin)); // GPIO bank
int n = PINNO(pin); // Pin number
RCC->AHB1ENR |= BIT(PINBANK(pin)); // Enable GPIO clock
gpio->MODER &= ~(3U << (n * 2)); // Clear existing setting
gpio->MODER |= (mode & 3) << (n * 2); // Set new mode
}
static inline void gpio_set_speed(uint16_t pin, uint8_t speed) {
GPIO_TypeDef *gpio = GPIO(PINBANK(pin)); // GPIO bank
int n = PINNO(pin); // Pin number
//gpio->OSPEEDR &= ~(3UL << (n * 2));
//gpio->OSPEEDR |= ~(((uint32_t) speed) << (n * 2));
SETBITS(gpio->OSPEEDR, 3UL << (n * 2), ((uint32_t) speed) << (n * 2));
}
static inline void gpio_set_af(uint16_t pin, uint8_t af) {
GPIO_TypeDef *gpio = GPIO(PINBANK(pin)); // GPIO bank
int n = PINNO(pin); // Pin number
//gpio->AFR[n >> 3] &= ~(15UL << ((n & 7) * 4));
//gpio->AFR[n >> 3] |= ((uint32_t) af_num) << ((n & 7) * 4);
SETBITS(gpio->AFR[n >> 3], 15UL << ((n & 7) * 4),
((uint32_t) af) << ((n & 7) * 4));
}
#endif
static inline void gpio_write(uint16_t pin, bool val) {
GPIO_TypeDef *gpio = GPIO(PINBANK(pin));
gpio->BSRR = (1U << PINNO(pin)) << (val ? 0 : 16);
}
static inline void gpio_toggle(uint16_t pin) {
GPIO_TypeDef *gpio = GPIO(PINBANK(pin)); // GPIO bank
uint32_t mask = BIT(PINNO(pin));
gpio->BSRR |= mask << (gpio->ODR & mask ? 16 : 0);
}
#define UART1 USART1
#define UART2 USART2
#define UART3 USART3
static inline void uart_init(USART_TypeDef *uart, unsigned long baud) {
// https://www.st.com/resource/en/datasheet/stm32f429zi.pdf
uint8_t af = 7; // Alternate function
uint16_t rx = 0, tx = 0; // pins
uint32_t freq = 0; // Bus frequency. UART1 is on APB2, rest on APB1
if (uart == UART1) freq = APB2_FREQUENCY, RCC->APB2ENR |= BIT(4);
if (uart == UART2) freq = APB1_FREQUENCY, RCC->APB1ENR |= BIT(17);
if (uart == UART3) freq = APB1_FREQUENCY, RCC->APB1ENR |= BIT(18);
if (uart == UART1) tx = PIN('A', 9), rx = PIN('A', 10);
if (uart == UART2) tx = PIN('A', 2), rx = PIN('A', 3);
if (uart == UART3) tx = PIN('D', 8), rx = PIN('D', 9);
gpio_init(tx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af);
gpio_init(rx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af);
uart->CR1 = 0; // Disable this UART
uart->BRR = freq / baud; // Set baud rate
uart->CR1 |= BIT(13) | BIT(2) | BIT(3); // Set UE, RE, TE
}
static inline void uart_write_byte(USART_TypeDef *uart, uint8_t byte) {
uart->DR = byte;
while ((uart->SR & BIT(7)) == 0) spin(1);
}
static inline void uart_write_buf(USART_TypeDef *uart, char *buf, size_t len) {
while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++);
}
static inline int uart_read_ready(USART_TypeDef *uart) {
return uart->SR & BIT(5); // If RXNE bit is set, data is ready
}
static inline uint8_t uart_read_byte(USART_TypeDef *uart) {
return (uint8_t) (uart->DR & 255);
}
static inline void clock_init(void) { // Set clock frequency
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
FLASH->ACR |= FLASH_LATENCY | BIT(8) |
BIT(9); // Flash latency, prefetch, Icache, Dcache
RCC->PLLCFGR &= ~((BIT(17) - 1)); // Clear PLL multipliers
RCC->PLLCFGR |= (((PLL_P - 2) / 2) & 3) << 16; // Set PLL_P
RCC->PLLCFGR |= PLL_M | (PLL_N << 6); // Set PLL_M and PLL_N
RCC->CR |= BIT(24); // Enable PLL
while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done
RCC->CFGR = (APB1_PRE << 10) | (APB2_PRE << 13); // Set prescalers
RCC->CFGR |= 2; // Set clock source to PLL
while ((RCC->CFGR & 12) == 0) spin(1); // Wait until done
}
@@ -0,0 +1,7 @@
#pragma once
#include <errno.h>
#define MG_ARCH MG_ARCH_FREERTOS
#define MG_ENABLE_MIP 1
#define MG_IO_SIZE 256
@@ -0,0 +1,157 @@
// Startup code
__attribute__((naked, noreturn)) void _reset(void) {
// Initialise memory
extern long _sbss, _ebss, _sdata, _edata, _sidata;
for (long *src = &_sbss; src < &_ebss; src++) *src = 0;
for (long *src = &_sdata, *dst = &_sidata; src < &_edata;) *src++ = *dst++;
// Call main()
extern void main(void);
main();
for (;;) (void) 0; // Infinite loop
}
void __attribute__((weak)) DefaultIRQHandler(void) {
for (;;) (void) 0;
}
#define WEAK_ALIAS __attribute__((weak, alias("DefaultIRQHandler")))
WEAK_ALIAS void NMI_Handler(void);
WEAK_ALIAS void HardFault_Handler(void);
WEAK_ALIAS void MemManage_Handler(void);
WEAK_ALIAS void BusFault_Handler(void);
WEAK_ALIAS void UsageFault_Handler(void);
WEAK_ALIAS void SVC_Handler(void);
WEAK_ALIAS void DebugMon_Handler(void);
WEAK_ALIAS void PendSV_Handler(void);
WEAK_ALIAS void SysTick_Handler(void);
WEAK_ALIAS void WWDG_IRQHandler(void);
WEAK_ALIAS void PVD_IRQHandler(void);
WEAK_ALIAS void TAMP_STAMP_IRQHandler(void);
WEAK_ALIAS void RTC_WKUP_IRQHandler(void);
WEAK_ALIAS void FLASH_IRQHandler(void);
WEAK_ALIAS void RCC_IRQHandler(void);
WEAK_ALIAS void EXTI0_IRQHandler(void);
WEAK_ALIAS void EXTI1_IRQHandler(void);
WEAK_ALIAS void EXTI2_IRQHandler(void);
WEAK_ALIAS void EXTI3_IRQHandler(void);
WEAK_ALIAS void EXTI4_IRQHandler(void);
WEAK_ALIAS void EXTI9_5_IRQHandler(void);
WEAK_ALIAS void EXTI15_10_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream0_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream1_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream2_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream3_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream4_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream5_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream6_IRQHandler(void);
WEAK_ALIAS void ADC_IRQHandler(void);
WEAK_ALIAS void CAN1_TX_IRQHandler(void);
WEAK_ALIAS void CAN1_RX0_IRQHandler(void);
WEAK_ALIAS void CAN1_RX1_IRQHandler(void);
WEAK_ALIAS void CAN1_SCE_IRQHandler(void);
WEAK_ALIAS void TIM1_BRK_TIM9_IRQHandler(void);
WEAK_ALIAS void TIM1_UP_TIM10_IRQHandler(void);
WEAK_ALIAS void TIM1_TRG_COM_TIM11_IRQHandler(void);
WEAK_ALIAS void TIM1_CC_IRQHandler(void);
WEAK_ALIAS void TIM2_IRQHandler(void);
WEAK_ALIAS void TIM3_IRQHandler(void);
WEAK_ALIAS void TIM4_IRQHandler(void);
WEAK_ALIAS void I2C1_EV_IRQHandler(void);
WEAK_ALIAS void I2C1_ER_IRQHandler(void);
WEAK_ALIAS void I2C2_EV_IRQHandler(void);
WEAK_ALIAS void I2C2_ER_IRQHandler(void);
WEAK_ALIAS void SPI1_IRQHandler(void);
WEAK_ALIAS void SPI2_IRQHandler(void);
WEAK_ALIAS void USART1_IRQHandler(void);
WEAK_ALIAS void USART2_IRQHandler(void);
WEAK_ALIAS void USART3_IRQHandler(void);
WEAK_ALIAS void RTC_Alarm_IRQHandler(void);
WEAK_ALIAS void OTG_FS_WKUP_IRQHandler(void);
WEAK_ALIAS void TIM8_BRK_TIM12_IRQHandler(void);
WEAK_ALIAS void TIM8_UP_TIM13_IRQHandler(void);
WEAK_ALIAS void TIM8_TRG_COM_TIM14_IRQHandler(void);
WEAK_ALIAS void TIM8_CC_IRQHandler(void);
WEAK_ALIAS void DMA1_Stream7_IRQHandler(void);
WEAK_ALIAS void FMC_IRQHandler(void);
WEAK_ALIAS void SDMMC1_IRQHandler(void);
WEAK_ALIAS void TIM5_IRQHandler(void);
WEAK_ALIAS void SPI3_IRQHandler(void);
WEAK_ALIAS void UART4_IRQHandler(void);
WEAK_ALIAS void UART5_IRQHandler(void);
WEAK_ALIAS void TIM6_DAC_IRQHandler(void);
WEAK_ALIAS void TIM7_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream0_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream1_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream2_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream3_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream4_IRQHandler(void);
WEAK_ALIAS void ETH_IRQHandler(void);
WEAK_ALIAS void ETH_WKUP_IRQHandler(void);
WEAK_ALIAS void CAN2_TX_IRQHandler(void);
WEAK_ALIAS void CAN2_RX0_IRQHandler(void);
WEAK_ALIAS void CAN2_RX1_IRQHandler(void);
WEAK_ALIAS void CAN2_SCE_IRQHandler(void);
WEAK_ALIAS void OTG_FS_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream5_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream6_IRQHandler(void);
WEAK_ALIAS void DMA2_Stream7_IRQHandler(void);
WEAK_ALIAS void USART6_IRQHandler(void);
WEAK_ALIAS void I2C3_EV_IRQHandler(void);
WEAK_ALIAS void I2C3_ER_IRQHandler(void);
WEAK_ALIAS void OTG_HS_EP1_OUT_IRQHandler(void);
WEAK_ALIAS void OTG_HS_EP1_IN_IRQHandler(void);
WEAK_ALIAS void OTG_HS_WKUP_IRQHandler(void);
WEAK_ALIAS void OTG_HS_IRQHandler(void);
WEAK_ALIAS void DCMI_IRQHandler(void);
WEAK_ALIAS void RNG_IRQHandler(void);
WEAK_ALIAS void FPU_IRQHandler(void);
WEAK_ALIAS void UART7_IRQHandler(void);
WEAK_ALIAS void UART8_IRQHandler(void);
WEAK_ALIAS void SPI4_IRQHandler(void);
WEAK_ALIAS void SPI5_IRQHandler(void);
WEAK_ALIAS void SPI6_IRQHandler(void);
WEAK_ALIAS void SAI1_IRQHandler(void);
WEAK_ALIAS void LTDC_IRQHandler(void);
WEAK_ALIAS void LTDC_ER_IRQHandler(void);
WEAK_ALIAS void DMA2D_IRQHandler(void);
// IRQ table
extern void _estack();
__attribute__((section(".vectors"))) void (*tab[16 + 91])(void) = {
// Cortex interrupts
_estack, _reset, NMI_Handler, HardFault_Handler,
MemManage_Handler, BusFault_Handler, UsageFault_Handler, 0, 0, 0, 0,
SVC_Handler, DebugMon_Handler, 0, PendSV_Handler, SysTick_Handler,
// Interrupts from peripherals
WWDG_IRQHandler, PVD_IRQHandler, TAMP_STAMP_IRQHandler, RTC_WKUP_IRQHandler,
FLASH_IRQHandler, RCC_IRQHandler, EXTI0_IRQHandler, EXTI1_IRQHandler,
EXTI2_IRQHandler, EXTI3_IRQHandler, EXTI4_IRQHandler,
DMA1_Stream0_IRQHandler, DMA1_Stream1_IRQHandler, DMA1_Stream2_IRQHandler,
DMA1_Stream3_IRQHandler, DMA1_Stream4_IRQHandler, DMA1_Stream5_IRQHandler,
DMA1_Stream6_IRQHandler, ADC_IRQHandler, CAN1_TX_IRQHandler,
CAN1_RX0_IRQHandler, CAN1_RX1_IRQHandler, CAN1_SCE_IRQHandler,
EXTI9_5_IRQHandler, TIM1_BRK_TIM9_IRQHandler, TIM1_UP_TIM10_IRQHandler,
TIM1_TRG_COM_TIM11_IRQHandler, TIM1_CC_IRQHandler, TIM2_IRQHandler,
TIM3_IRQHandler, TIM4_IRQHandler, I2C1_EV_IRQHandler, I2C1_ER_IRQHandler,
I2C2_EV_IRQHandler, I2C2_ER_IRQHandler, SPI1_IRQHandler, SPI2_IRQHandler,
USART1_IRQHandler, USART2_IRQHandler, USART3_IRQHandler,
EXTI15_10_IRQHandler, RTC_Alarm_IRQHandler, OTG_FS_WKUP_IRQHandler,
TIM8_BRK_TIM12_IRQHandler, TIM8_UP_TIM13_IRQHandler,
TIM8_TRG_COM_TIM14_IRQHandler, TIM8_CC_IRQHandler, DMA1_Stream7_IRQHandler,
FMC_IRQHandler, SDMMC1_IRQHandler, TIM5_IRQHandler, SPI3_IRQHandler,
UART4_IRQHandler, UART5_IRQHandler, TIM6_DAC_IRQHandler, TIM7_IRQHandler,
DMA2_Stream0_IRQHandler, DMA2_Stream1_IRQHandler, DMA2_Stream2_IRQHandler,
DMA2_Stream3_IRQHandler, DMA2_Stream4_IRQHandler, ETH_IRQHandler,
ETH_WKUP_IRQHandler, CAN2_TX_IRQHandler, CAN2_RX0_IRQHandler,
CAN2_RX1_IRQHandler, CAN2_SCE_IRQHandler, OTG_FS_IRQHandler,
DMA2_Stream5_IRQHandler, DMA2_Stream6_IRQHandler, DMA2_Stream7_IRQHandler,
USART6_IRQHandler, I2C3_EV_IRQHandler, I2C3_ER_IRQHandler,
OTG_HS_EP1_OUT_IRQHandler, OTG_HS_EP1_IN_IRQHandler, OTG_HS_WKUP_IRQHandler,
OTG_HS_IRQHandler, DCMI_IRQHandler, 0, RNG_IRQHandler, FPU_IRQHandler,
UART7_IRQHandler, UART8_IRQHandler, SPI4_IRQHandler, SPI5_IRQHandler,
SPI6_IRQHandler, SAI1_IRQHandler, LTDC_IRQHandler, LTDC_ER_IRQHandler,
DMA2D_IRQHandler};
@@ -0,0 +1,42 @@
#include "mcu.h"
int _write(int fd, char *ptr, int len) {
(void) fd, (void) ptr, (void) len;
if (fd == 1) uart_write_buf(UART3, ptr, (size_t) len);
return len;
}
int _fstat(int fd, struct stat *st) {
(void) fd, (void) st;
return -1;
}
void *_sbrk(int incr) {
extern char _end;
static unsigned char *heap = NULL;
unsigned char *prev_heap;
if (heap == NULL) heap = (unsigned char *) &_end;
prev_heap = heap;
heap += incr;
return prev_heap;
}
int _close(int fd) {
(void) fd;
return -1;
}
int _isatty(int fd) {
(void) fd;
return 1;
}
int _read(int fd, char *ptr, int len) {
(void) fd, (void) ptr, (void) len;
return -1;
}
int _lseek(int fd, int ptr, int dir) {
(void) fd, (void) ptr, (void) dir;
return 0;
}
@@ -0,0 +1,48 @@
CFLAGS ?= -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion \
-Wformat-truncation -fno-common -Wconversion \
-g3 -Os -ffunction-sections -fdata-sections \
-I. -Iinclude -I../../.. \
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 $(EXTRA_CFLAGS)
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = main.c startup.c syscalls.c ../../../mongoose.c
TINYUSB_VERSION ?= 0.14.0
TINYUSB_REPO ?= https://github.com/hathach/tinyusb
SOURCES += tinyusb/src/tusb.c \
tinyusb/src/common/tusb_fifo.c \
tinyusb/src/device/usbd.c \
tinyusb/src/device/usbd_control.c \
tinyusb/src/class/net/ecm_rndis_device.c \
tinyusb/src/class/net/ncm_device.c \
tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c \
tinyusb/lib/networking/rndis_reports.c \
usb_descriptors.c
CFLAGS += -Itinyusb/src -Itinyusb/lib/networking
CFLAGS += -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_MIP=1 -DMG_ENABLE_PACKED_FS=1 -DMG_IO_SIZE=512 -DMG_ENABLE_CUSTOM_MILLIS=1
CFLAGS += -DSTM32F429xx
CFLAGS += -Wno-conversion -Wno-sign-conversion
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F
else
RM = rm -f
endif
all build example: firmware.bin
tinyusb:
git clone --depth 1 -b $(TINYUSB_VERSION) $(TINYUSB_REPO) $@
$(SOURCES): tinyusb
firmware.elf: $(SOURCES)
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
flash: firmware.bin
st-flash --reset write firmware.bin 0x8000000
clean:
$(RM) firmware.*
@@ -0,0 +1,266 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.0.4
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/*
* 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.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,39 @@
/**************************************************************************//**
* @file cmsis_version.h
* @brief CMSIS Core(M) Version definitions
* @version V5.0.2
* @date 19. April 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CMSIS_VERSION_H
#define __CMSIS_VERSION_H
/* CMSIS Version definitions */
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
#endif
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,270 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for Armv7-M MPU
* @version V5.0.4
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2017-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_MPU_ARMV7_H
#define ARM_MPU_ARMV7_H
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) \
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
((Region) & MPU_RBAR_REGION_Msk) | \
(MPU_RBAR_VALID_Msk))
/**
* MPU Memory Access Attributes
*
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
*/
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
((((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) ) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk)))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
/**
* MPU Memory Access Attribute for strongly ordered memory.
* - TEX: 000b
* - Shareable
* - Non-cacheable
* - Non-bufferable
*/
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
/**
* MPU Memory Access Attribute for device memory.
* - TEX: 000b (if non-shareable) or 010b (if shareable)
* - Shareable or non-shareable
* - Non-cacheable
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
*
* \param IsShareable Configures the device memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
/**
* MPU Memory Access Attribute for normal memory.
* - TEX: 1BBb (reflecting outer cacheability rules)
* - Shareable or non-shareable
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
*
* \param OuterCp Configures the outer cache policy.
* \param InnerCp Configures the inner cache policy.
* \param IsShareable Configures the memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U))
/**
* MPU Memory Access Attribute non-cacheable policy.
*/
#define ARM_MPU_CACHEP_NOCACHE 0U
/**
* MPU Memory Access Attribute write-back, write and read allocate policy.
*/
#define ARM_MPU_CACHEP_WB_WRA 1U
/**
* MPU Memory Access Attribute write-through, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WT_NWA 2U
/**
* MPU Memory Access Attribute write-back, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WB_NWA 3U
/**
* Struct for a single MPU Region
*/
typedef struct {
uint32_t RBAR; //!< The region base address register value (RBAR)
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DSB();
__ISB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable(void)
{
__DSB();
__ISB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
MPU->RNR = rnr;
MPU->RASR = 0U;
}
/** Configure an MPU region.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
{
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
{
MPU->RNR = rnr;
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Memcopy with strictly ordered memory access, e.g. for register targets.
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0U; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
{
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
while (cnt > MPU_TYPE_RALIASES) {
orderedCpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
table += MPU_TYPE_RALIASES;
cnt -= MPU_TYPE_RALIASES;
}
orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
}
#endif
Loaded 100 of 273 files, more files were not shown because too many files have changed in this diff. Show more