Compare commits

..
224 Commits
Author SHA1 Message Date
Sergio R. Caprile 32559f15ea fix Github editor line ending creativity 2023-10-12 10:56:38 -03:00
Sergio R. Caprile b10eef1e32 Update version in mongoose.h 2023-10-12 10:44:58 -03:00
Sergio R. Caprile 7c4911598c Update version.h 2023-10-12 10:27:55 -03:00
Sergio R. Caprile efacb20bdc Merge pull request #2423 from cesanta/same
rename same54
2023-10-11 17:36:09 -03:00
Sergio R. Caprile 2e6188205f rename same54 2023-10-11 16:58:21 -03:00
Sergio R. Caprile 83fec2cf45 cleanup 2023-10-11 16:39:24 -03:00
Sergio R. Caprile 9be36eb9cb Merge pull request #2422 from cesanta/tcp
Fix tcp example for 2-way TLS
2023-10-11 16:34:12 -03:00
Sergio R. Caprile a51802ecaf Fix tcp example for 2-way TLS 2023-10-11 16:25:24 -03:00
Sergio R. Caprile b1c220e610 Remove mg_mkpipe() leftovers 2023-10-10 18:16:02 -03:00
Sergey Lyubka 36f6b805e3 Merge pull request #2421 from cesanta/h723
Add h723 example
2023-10-10 19:19:51 +01:00
Sergey Lyubka 64efad9e46 Merge pull request #2419 from cesanta/rt1020
Add FreeRTOS example for RT1020
2023-10-10 07:57:05 +01:00
Sergio R. Caprile 8a8d5ce151 Add FreeRTOS example for RT1020 2023-10-09 17:03:58 -03:00
Sergey Lyubka 907417f9ec Merge pull request #2418 from cesanta/rt1020
Add TRNG
2023-10-09 17:24:39 +01:00
Sergio R. Caprile 0965177e72 Add TRNG 2023-10-09 13:03:52 -03:00
cpq 7d07ca8427 Add drivers 2023-10-09 09:36:43 +01:00
Sergey Lyubka d18b2b390a Merge pull request #2415 from cesanta/json
Add mg_json_next() for iterating objects/arrays
2023-10-09 07:55:44 +01:00
Sergey Lyubka fefe8b1c15 Merge pull request #2416 from cesanta/log
Add MG_ENABLE_CUSTOM_LOG
2023-10-09 07:55:31 +01:00
cpq ea2ff010a9 Add MG_ENABLE_CUSTOM_LOG 2023-10-08 17:09:14 +01:00
cpq e357cb3185 Bump up max DNS responses 10->15 2023-10-08 15:30:18 +01:00
cpq 293ee2162c Add mg_json_next() for iterating objects/arrays 2023-10-07 22:40:51 +01:00
cpq c29ee769bc Fix comment 2023-10-07 17:58:20 +01:00
Sergey Lyubka 82399f1561 Merge pull request #2414 from cesanta/rt1020
Rework  RT1020 driver
2023-10-07 11:21:29 +01:00
Sergio R. Caprile 9255ceaf8a Rework RT1020 driver
Add web server in example
Add to tests
2023-10-06 16:56:00 -03:00
cpq bb9c7c0eb3 Handle ECOS case in accept_conn() 2023-10-06 15:58:26 +01:00
Sergey Lyubka 8ec327f9c7 Merge pull request #2407 from cesanta/rt1020
Add RT1020-EVK baremetal example
2023-10-05 14:19:00 +01:00
Sergio R. Caprile c9b982eaff add update script to Makefile 2023-10-04 16:31:50 -03:00
Sergio R. Caprile 248e7b6e29 Add RT1020-EVK baremetal example 2023-10-04 15:18:57 -03:00
Sergey Lyubka cb1ae312a1 Merge pull request #2404 from cesanta/g031
Add nucleo-g031 baremetal example
2023-10-04 15:39:19 +01:00
cpq aec25cf547 Add h723 example 2023-10-04 11:11:56 +01:00
cpq 4db3fc2515 dd nucleo-g031 baremetal example 2023-10-03 13:55:47 +01:00
Sergey Lyubka 79d6017c56 Merge pull request #2402 from cesanta/bcast
send broadcasts in MIP
2023-10-03 13:53:58 +01:00
Sergio R. Caprile d4c122b17a send broadcasts in MIP 2023-10-02 13:37:27 -03:00
cpq 57fd93eeda Fix ring color 2023-10-01 23:20:42 +01:00
cpq 19cac05747 Enhance components 2023-10-01 23:08:10 +01:00
Sergey Lyubka 5ebede5096 Merge pull request #2395 from cesanta/scopeid
Fix #2192 - honor addr%scopeid ipv6 notation
2023-09-29 15:52:40 +01:00
cpq 46ecb07fc8 Fix #2192 - honor addr%scopeid ipv6 notation 2023-09-29 15:49:47 +01:00
cpq a628a05efb Restore pub. domain notice 2023-09-29 13:09:29 +01:00
cpq fc626bb57f Update pakced fs 2023-09-28 16:27:58 +01:00
cpq 1291839182 Update packed fs 2023-09-28 15:09:34 +01:00
Sergey Lyubka 736e7a2cf9 Merge pull request #2394 from cesanta/chunks
Get rid of MG_EV_HTTP_CHUNK
2023-09-26 20:45:40 +01:00
cpq 7884a2f3c7 Get rid of MG_EV_HTTP_CHUNK 2023-09-26 20:45:24 +01:00
Sergey Lyubka dde699ffda Merge pull request #2393 from cesanta/ota-api-refactoring
OTA API refactoring: renamed files and defines
2023-09-26 14:15:49 +01:00
robert fa54a22aed OTA API refactoring: renamed files and defines 2023-09-26 08:33:39 -04:00
cpq 822b0c011a Add sys_flash.c for common mg_flash_{load,save} 2023-09-25 07:55:35 +01:00
cpq a0f8a197c9 Split sys.h API over MG_SYS_* 2023-09-25 07:33:38 +01:00
Sergey Lyubka 7e75e51332 Merge pull request #2392 from cesanta/flash2
Commonise flash-based OTA. Add h7 support.
2023-09-25 05:21:52 +01:00
cpq b37efbe891 Commonise flash-based OTA. Add h7 support. 2023-09-24 21:55:49 +01:00
cpq 6e648c90b0 Added OTA to the feature list 2023-09-24 21:18:02 +01:00
cpq 377d6acc74 Fix leak in unit test 2023-09-22 08:12:09 +01:00
Sergey Lyubka f552d15fe4 Merge pull request #2390 from cesanta/tickets
Restore tickets support
2023-09-21 19:08:08 +01:00
cpq d1204e8a66 Better chunk length calculation 2023-09-21 19:04:32 +01:00
cpq 9ec48e41f7 Restore tickets support 2023-09-21 18:43:33 +01:00
Sergey Lyubka 9055a83b4f Merge pull request #2388 from cesanta/dns
dns.c slight refactor, no functional changes
2023-09-21 13:38:23 +01:00
cpq dd047b2613 dns.c slight refactor, no functional changes 2023-09-21 13:38:06 +01:00
Sergey Lyubka b7a32069b1 Merge pull request #2389 from cesanta/ipv6
Address discussions/2305 - bind to v6 only / v6 and v4
2023-09-21 13:37:29 +01:00
cpq 00d475bc7e Address https://github.com/cesanta/mongoose/discussions/2305 - bind to v6 only / v6 and v4 2023-09-21 12:35:47 +01:00
Sergio R. Caprile 33ab44430c Merge pull request #2386 from cesanta/timer
Revert to the old TLS API, but keep certs as mg_str for DER
2023-09-19 12:17:56 -03:00
Sergio R. Caprile b355da32b9 Add GA OpenSSL tests back 2023-09-19 12:08:02 -03:00
cpq 3f0366a514 Revert to the old TLS API, but keep certs as mg_str for DER 2023-09-19 11:15:23 +01:00
cpq 7ecbbc517d Using mg_bzero to cleanup memory in mg_close_conn() 2023-09-17 22:25:36 +01:00
cpq a04c94444e Add rt1020 baremetal sketch 2023-09-17 10:41:04 +01:00
Sergio R. Caprile 42b9ac1145 update 2023-09-12 18:30:23 -03:00
Sergio R. Caprile 7be4925c70 Merge pull request #2384 from cesanta/p_open
Do not use CLOEXEC on Windows
2023-09-12 18:28:39 -03:00
Sergio R. Caprile 7b19568683 Do not use CLOEXEC on Windows 2023-09-12 17:11:55 -03:00
Sergio R. Caprile 8f56779855 Merge pull request #2383 from cesanta/poll
Optimize test coverage
2023-09-12 16:41:17 -03:00
Sergio R. Caprile fdfad8462c Optimize test coverage 2023-09-12 16:28:10 -03:00
Sergio R. Caprile 3773ef45e7 Optimize test coverage 2023-09-12 16:22:54 -03:00
Sergio R. Caprile c0ca3cacb4 Fixing test.yml 2023-09-12 15:05:29 -03:00
Sergio R. Caprile bed0630698 Fixing test.yml 2023-09-12 09:13:38 -03:00
Sergey Lyubka 53baa18836 Merge pull request #2380 from cesanta/ip-fragmentation-2
IP fragmentation send path: added TCP/UDP packet splitting to fit within MTU
2023-09-12 12:51:04 +01:00
Sergey Lyubka 32a2144426 Merge pull request #2382 from cesanta/poll
increase test coverage
2023-09-12 12:50:50 +01:00
robert 264026acde added TCP/UDP packet splitting to fit within MTU 2023-09-12 07:05:13 -04:00
Sergio R. Caprile 43503ef73a increase test coverage 2023-09-11 17:46:25 -03:00
Sergio R. Caprile 7f52717e9d increase test coverage 2023-09-11 17:41:36 -03:00
Sergio R. Caprile bd59185ef1 Merge pull request #2381 from cesanta/tls
add host only validation
2023-09-11 16:38:18 -03:00
Sergio R. Caprile 310ffcd4eb add host only validation 2023-09-11 16:34:24 -03:00
cpq d23664a457 Move network code to net.* 2023-09-08 09:39:57 +01:00
Sergio R. Caprile a1e316ddcf make TCP example work with new TLS API 2023-09-06 18:50:33 -03:00
Sergio R. Caprile e328758fc7 Merge pull request #2379 from cesanta/tls
unifomize TLS examples, stage 1
2023-09-06 16:55:46 -03:00
Sergio R. Caprile dbf49255a3 fix 2023-09-06 16:19:21 -03:00
Sergio R. Caprile 1391bdcf8b remove certs.h 2023-09-06 15:49:02 -03:00
Sergio R. Caprile d8106a8ffe use packed ca.pem 2023-09-06 15:21:16 -03:00
Sergio R. Caprile ae55789c4b erase ca.pem 2023-09-06 15:21:16 -03:00
Sergio R. Caprile ec02ccf5b2 Merge pull request #2377 from cesanta/h5
uniformize examples
2023-09-05 13:43:39 -03:00
Sergio R. Caprile f970cd78d7 uniformize examples 2023-09-05 13:36:46 -03:00
Sergio R. Caprile 8140ea16a7 Merge pull request #2371 from cesanta/cloexec
Fix #2369 - set CLOEXEC on epoll and regular file fds
2023-09-05 10:15:58 -03:00
Sergey Lyubka 2883709756 Merge pull request #2370 from cesanta/ota
Add OTA to the device dashboard. Implement for H5
2023-09-05 13:28:22 +01:00
cpq ca4c2c6c41 Set CLOEXEC on epoll and regular file fds 2023-09-05 06:56:41 +01:00
Sergey Lyubka fbc56f4adf Merge pull request #2367 from cesanta/ip-fragmentation
closing connection if a fragmented packet is received
2023-09-05 06:34:29 +01:00
cpq 2f014237b2 Add OTA to the device dashboard. Implement for H5 2023-09-04 22:07:32 +01:00
robert f33e3a7752 closing connection if a fragmented packet is received 2023-08-30 10:30:51 -04:00
cpq d5b5cec797 Make fuzzer faster on large input/output 2023-08-26 00:52:24 +01:00
Sergey Lyubka f8e1f17651 Merge pull request #2366 from cesanta/h5
Add FreeRTOS example on H5
2023-08-25 21:21:41 +01:00
Sergio R. Caprile be58bfe22b Add FreeRTOS example on H5 2023-08-25 17:15:26 -03:00
Sergey Lyubka 995a63dc39 Merge pull request #2364 from cesanta/braces
Style: always braces around if + else
2023-08-25 15:00:52 +01:00
cpq e8d57ac4e1 Style: always braces around if + else 2023-08-25 14:46:38 +01:00
Sergio R. Caprile eab3a83548 Merge pull request #2362 from cesanta/h5
Update H5 HAL, enable RNG, work at 250MHz, add to tests
2023-08-24 13:35:37 -03:00
Sergio R. Caprile 3fb9e5fd56 Update H5 HAL, enable RNG, work at 250MHz, add to tests 2023-08-24 13:32:37 -03:00
Sergio R. Caprile 41448278cf Merge pull request #2360 from cesanta/h7
Fix sysinit in H7
2023-08-23 14:37:21 -03:00
cpq 48516b43c5 Use device 11 2023-08-23 00:38:57 +01:00
Sergio R. Caprile 80b7be0568 Fix sysinit in H7 2023-08-22 19:58:19 -03:00
Sergey Lyubka 4183552aee Merge pull request #2358 from cesanta/b64
Change base64 API
2023-08-22 14:43:33 +01:00
cpq 527e89754e Change base64 API 2023-08-22 12:11:13 +01:00
robertc2000 30e0f42c97 Merge pull request #2357 from cesanta/tcpip-conn-init
improved tcp connection initiation
2023-08-22 09:30:24 +03:00
Sergio R. Caprile 39b40daf5d cleanup 2023-08-21 19:34:04 -03:00
Sergio R. Caprile 94636f4d30 Merge pull request #2355 from cesanta/mqtt54
Add MQTT example and test for SAME54
2023-08-21 19:27:17 -03:00
Sergio R. Caprile fd53548c5e Add MQTT example and test for SAME54 2023-08-21 19:24:33 -03:00
Sergio R. Caprile 354ea30797 Add MQTT example and test for SAME54 2023-08-21 19:11:50 -03:00
Sergio R. Caprile 11303e0dc1 Merge pull request #2354 from cesanta/tst
Add MQTT test for MIP
2023-08-21 17:26:24 -03:00
Sergio R. Caprile b4c645f703 Add MQTT test for MIP 2023-08-21 17:22:42 -03:00
cpq 3256218fd2 Do uri len check after it is finalised 2023-08-21 17:16:48 +01:00
robert a4f14b0ddf improved tcp connection initiation 2023-08-21 10:22:53 -04:00
Sergio R. Caprile e7459d91f9 Merge pull request #2353 from cesanta/certs
Store certs in certs/. Add mg_unpacked()
2023-08-21 09:52:10 -03:00
cpq b32d1c15f0 Store certs in certs/. Add mg_unpacked() 2023-08-20 23:43:04 +01:00
Sergio R. Caprile 1e0d57a832 Merge pull request #2352 from cesanta/mip
Unify naming: all network stacks are in src/net_...
2023-08-18 16:40:57 -03:00
cpq f3617a1cf3 Add integer overflow protection 2023-08-18 20:33:57 +01:00
cpq 89a9a50b96 Unify naming: all network stacks are in src/net_... 2023-08-18 19:59:15 +01:00
cpq 69d2ba7316 Add example for nucleo-h563zi 2023-08-18 16:06:17 +01:00
robertc2000 3ea5f8dbde Merge pull request #2344 from cesanta/tcp-closure
improved tcp closure
2023-08-18 14:06:41 +03:00
Sergio R. Caprile d56152875d Merge pull request #2350 from cesanta/deprecate
deprecate mg_mkpipe()
2023-08-17 18:32:39 -03:00
Sergio R. Caprile 7459d30a28 deprecate mg_mkpipe() 2023-08-17 18:05:03 -03:00
Sergio R. Caprile 16bf9101aa Merge pull request #2349 from cesanta/isclosing
is_closing -> is_draining
2023-08-17 16:52:51 -03:00
Sergio R. Caprile 2b20af36a7 is_closing -> is_draining 2023-08-17 16:45:10 -03:00
robert f5e87cceec improved tcp closure 2023-08-17 10:34:31 -04:00
Sergey Lyubka 36fcb7ed21 Merge pull request #2347 from cesanta/cl
Fix #2322 - stricter Content-Length check, allow 1*DIGIT only
2023-08-17 14:58:01 +01:00
cpq 9fe7807b02 Fix #2322 - stricter Content-Length check, allow 1*DIGIT only 2023-08-17 12:55:08 +01:00
Sergey Lyubka 88e3017ee5 Merge pull request #2348 from cesanta/dns
Fix #2263 - allow multiple errors in DNS handler
2023-08-17 10:12:16 +01:00
cpq 17f3738192 Fix #2263 - allow multiple errors in DNS handler 2023-08-17 10:11:21 +01:00
Sergey Lyubka 6cfdc39005 Merge pull request #2346 from cesanta/regex
Fix #2345 - json parsing of arrays of objects
2023-08-16 22:10:13 +01:00
cpq 58886a9693 Fix #2345 - json parsing of arrays of objects 2023-08-16 22:09:45 +01:00
Sergey Lyubka 66e022c454 Merge pull request #2343 from cesanta/fuz
Add http serve to fuzzer
2023-08-16 20:46:27 +01:00
cpq ea3968601e Add http serve to fuzzer 2023-08-16 20:18:52 +01:00
Sergio R. Caprile 54be13d1d8 Merge pull request #2342 from cesanta/pio
Fix PIO assembly error
2023-08-14 16:17:37 -03:00
Sergio R. Caprile 22ea825d46 Fix PIO assembly error 2023-08-14 16:15:27 -03:00
Sergio R. Caprile 8c03aa2801 nit 2023-08-10 19:37:47 -03:00
Sergio R. Caprile 5bb952260a Merge pull request #2340 from cesanta/same54
SAME54 Ethernet driver
2023-08-10 19:26:50 -03:00
Sergio R. Caprile face6c44c6 SAME54 Ethernet driver
Add tls_builtin.c
2023-08-10 18:59:23 -03:00
Sergio R. Caprile 66c2bfe822 Merge pull request #2339 from cesanta/revert-2336-foo
Revert "Foo"
2023-08-10 18:16:38 -03:00
Sergio R. Caprile 3721bcc790 Revert "Foo" 2023-08-10 17:48:55 -03:00
Sergio R. Caprile cacab6fe4c Merge pull request #2338 from cesanta/keil
Keil
2023-08-09 17:17:57 -03:00
scaprile 6ad8674cd4 Add F4 Keil examples 2023-08-09 14:23:10 -03:00
novlean 847990ce49 Update README.md
Added URL to https://mongoose.ws/integration/
2023-08-09 17:50:57 +01:00
scaprile 1bfdc1f138 Add hw testing 2023-08-08 17:16:15 -03:00
Sergio R. Caprile 58367fe23e Merge pull request #2337 from cesanta/h7f
add H7 FreeRTOS example
2023-08-08 15:32:29 -03:00
Sergio R. Caprile a8712e2307 add H7 FreeRTOS example 2023-08-08 14:38:41 -03:00
robertc2000 8acfae1111 Merge pull request #2336 from cesanta/foo
Foo
2023-08-08 09:26:48 +03:00
cpq 70fc71c6f7 Changes 2023-08-07 06:18:49 -04:00
Sergio R. Caprile dd5118cab0 Merge pull request #2332 from cesanta/cube
update Cube test Makefile to support testing packaged examples
2023-08-04 17:11:22 -03:00
Sergio R. Caprile 2d75a6ccd4 update 2023-08-04 15:37:57 -03:00
Sergio R. Caprile e004ab1693 Merge pull request #2331 from cesanta/makefile
update Makefile
2023-08-04 14:45:56 -03:00
Sergio R. Caprile acddfc3bf4 update Makefile 2023-08-04 14:32:28 -03:00
cpq 519d4b0286 Changes 2023-08-04 13:53:01 +01:00
cpq 8005a5e687 Changes 2023-08-04 13:53:01 +01:00
cpq f5943fe591 Add tls_builtin.c 2023-08-04 13:53:01 +01:00
cpq cea7fcdb37 AVR build fixes 2023-08-04 13:52:59 +01:00
robert b5213c13dd SAME54 Ethernet driver 2023-08-04 13:48:55 +01:00
Sergio R. Caprile 3a06b4833c Merge pull request #2330 from cesanta/timeout
Timeout
2023-08-03 14:52:54 -03:00
Sergio R. Caprile 5cdf6c1d05 Add SYN timeout 2023-08-03 14:23:14 -03:00
Sergio R. Caprile 5754e5dd59 fix ARP timeout 2023-08-03 13:42:56 -03:00
Sergio R. Caprile e5ab1c454b Merge pull request #2329 from cesanta/arp
Implement ARP resolution for local LANs
2023-08-03 11:02:43 -03:00
cpq 697576b63c Implement ARP resolution for local LANs 2023-08-03 13:48:23 +01:00
Sergio R. Caprile 2db41aef09 Merge pull request #2328 from cesanta/ft
standardize example names
2023-08-02 16:20:05 -03:00
Sergio R. Caprile 7f4ad3cade standardize example names 2023-08-02 16:07:54 -03:00
Sergio R. Caprile 74c4c32082 Merge pull request #2327 from cesanta/rndis
standardize example names
2023-08-02 14:24:07 -03:00
Sergio R. Caprile 30d545443c standardize example names 2023-08-02 14:03:11 -03:00
Sergio R. Caprile dedba52315 Merge pull request #2325 from cesanta/fpu
FP unit in H743 is dp
2023-08-01 17:06:54 -03:00
Sergio R. Caprile 481f7b5cff FP unit in H743 is dp 2023-08-01 17:02:05 -03:00
Sergio R. Caprile 6ce4f4930c Merge pull request #2324 from cesanta/fb
standardize example names
2023-08-01 15:46:58 -03:00
Sergio R. Caprile e33a10db75 standardize example names 2023-08-01 15:24:28 -03:00
Sergio R. Caprile ef17055145 Merge pull request #2323 from cesanta/cube
standardize example names
2023-07-31 18:27:34 -03:00
Sergio R. Caprile 6a2fa10a4e standardize example names 2023-07-31 17:47:56 -03:00
Sergio R. Caprile 6b81a5846d Merge pull request #2320 from cesanta/2308collaterals
fix autogenerated
2023-07-28 17:47:49 -03:00
Sergio R. Caprile b54d086fde fix autogenerated 2023-07-28 17:06:58 -03:00
Sergio R. Caprile 5ee9d22263 momentarily disable MacOS OpenSSL tests 2023-07-26 15:53:59 -03:00
Sergio R. Caprile 7dcb097a5d momentarily disable OpenSSL tests 2023-07-26 15:49:03 -03:00
Sergio R. Caprile 29a30239ab momentarily disable OpenSSL tests 2023-07-26 15:33:30 -03:00
Sergio R. Caprile ed54b60ea3 update to new API 2023-07-25 18:41:41 -03:00
Sergio R. Caprile 199af33b30 update to new TLS API 2023-07-25 14:26:14 -03:00
Sergio R. Caprile adfa1d0e20 fix mongoose.h 2023-07-25 13:22:41 -03:00
Sergio R. Caprile ef25c42e86 fix unit tests for older compilers 2023-07-25 11:55:01 -03:00
Sergio R. Caprile 91a638156c Merge branch 'master' of https://github.com/cesanta/mongoose 2023-07-25 11:37:01 -03:00
Sergio R. Caprile 26ce666938 Merge branch 'master' of https://github.com/cesanta/mongoose 2023-07-25 11:35:29 -03:00
cpq 7548af895b H7 mbedtls build fixed 2023-07-25 15:34:22 +01:00
Sergio R. Caprile 9548437a9e update unit tests for new API 2023-07-25 11:27:01 -03:00
cpq 5e50b7104c Unit test fixed 2023-07-25 15:26:47 +01:00
cpq d824cf7dbd Add mbedtls to H7 baremetal 2023-07-25 15:03:01 +01:00
cpq 0613cc62f4 TLS API refactor 2023-07-25 13:07:28 +01:00
Sergey Lyubka d9cbcb5fa8 Merge pull request #2312 from cesanta/arduino
no Docker, in-place build for tests
2023-07-22 01:09:35 +01:00
Sergio R. Caprile a4f5355161 no Docker, in-place build for tests 2023-07-21 16:45:14 -03:00
Sergey Lyubka a24b6c1909 Merge pull request #2309 from cesanta/arduino
move Arduino tests to its dir
2023-07-21 14:33:00 +01:00
Sergio R. Caprile fd7dc72410 Merge pull request #2310 from cesanta/am
Add arduino/w5500-mqtt example
2023-07-21 10:27:20 -03:00
cpq e4f4dfab3b Add arduino/w5500-mqtt example 2023-07-21 13:54:41 +01:00
Sergio R. Caprile 66010be5a6 move Arduino tests to its dir 2023-07-20 20:22:06 -03:00
Sergio R. Caprile 852c42a8f3 static clue 2023-07-20 16:34:13 -03:00
Sergio R. Caprile 132725de7b Merge pull request #2308 from cesanta/nano
AVR build fixes
2023-07-20 14:12:49 -03:00
cpq 0a761c09e3 AVR build fixes 2023-07-20 16:07:53 +01:00
Sergey Lyubka 09ce6ae1c5 Merge pull request #2307 from cesanta/codeql
add CodeQL analysis
2023-07-20 14:37:18 +01:00
Sergio R. Caprile 85e60ed858 force run 2023-07-19 16:21:14 -03:00
Sergio R. Caprile 86fd18324b codeql 2023-07-19 16:14:44 -03:00
Sergio R. Caprile fdf82e5d6c codeql 2023-07-19 15:10:28 -03:00
Sergio R. Caprile eb0b1580d1 nits 2023-07-19 14:53:29 -03:00
Sergio R. Caprile 2d33c545b8 codeql 2023-07-19 14:53:29 -03:00
Sergio R. Caprile cdaf523aa8 codeql 2023-07-19 14:53:29 -03:00
Sergio R. Caprile 3195f2cec2 codeql 2023-07-19 14:53:29 -03:00
cpq ea89a4afab Revert "Integration page"
This reverts commit 3415b62d2d.
2023-07-19 18:50:27 +01:00
cpq 3415b62d2d Integration page 2023-07-19 16:25:14 +01:00
Sergey Lyubka ee80822564 Merge pull request #2306 from cesanta/nits
Nits
2023-07-19 06:00:32 +01:00
cpq 3c9e218d07 Nits 2023-07-19 05:08:28 +01:00
Sergio R. Caprile 387a602885 Merge pull request #2304 from cesanta/addressing
Addressing
2023-07-18 17:30:35 -03:00
Sergio R. Caprile ef0ff43975 static clue 2023-07-18 17:23:50 -03:00
Sergio R. Caprile ae37407369 static clue 2023-07-18 17:10:05 -03:00
cpq e1c91b5763 Merge branch 'master' of github.com:cesanta/mongoose 2023-07-18 17:47:02 +01:00
cpq c49b472f92 Ignore DHCP for static IP config 2023-07-18 17:46:52 +01:00
Sergey Lyubka 0a6b1b9418 Merge pull request #2297 from cesanta/2251-implement-tcp-retransmit-in-mip
implemented tcp retransmission
2023-07-16 04:53:06 +01:00
Sergio R. Caprile ac40673a9e test for retransmitted segment 2023-07-12 11:22:35 -04:00
cpq 818f99b286 Update examples to adopt to the new iface state 2023-07-12 14:09:30 +01:00
robert 320da5e84c implemented tcp retransmission 2023-07-11 06:20:47 -04:00
Sergey Lyubka 6957c379d5 Merge pull request #2294 from cesanta/hdr
Fix #2292 - fail on stray \r character in headers
2023-07-09 23:08:22 +01:00
cpq 88e880f107 Fix #2292 - fail on stray \r character in headers 2023-07-09 18:18:18 +01:00
cpq bf8c4dfc83 Merge branch 'master' of github.com:cesanta/mongoose 2023-07-07 08:44:33 +01:00
cpq 5dff282132 Fix #2293 - stricter header validity check 2023-07-07 08:44:25 +01:00
Sergio R. Caprile 1148ac0ae4 Merge pull request #2289 from cesanta/acl
update `mg_check_ip_acl`
2023-07-05 18:06:28 -03:00
Sergio R. Caprile 59c46fc594 update 2023-07-05 17:49:18 -03:00
cpq 03a94e3a6a Use \r\n for log messages, for terminal apps 2023-07-05 10:26:27 +01:00
1275 changed files with 43363 additions and 12386 deletions

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
name: "CodeQL Scanning"
# https://github.com/github/codeql-action
on:
push:
paths:
- "Makefile"
- "mongoose.c"
- "mongoose.h"
- test/unit-test
- test/mip-test
env:
IPV6: 0
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
permissions:
security-events: write
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: cpp
- run: |
make test CC=gcc ASAN= ASAN_OPTIONS=
./test/setup_ga_network.sh && make mip_test CC=gcc ASAN= ASAN_OPTIONS=
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
+135 -46
View File
@@ -15,11 +15,22 @@ jobs:
matrix:
cc: [gcc, clang, g++, clang++]
target: [test, mip_test]
ssl: [MBEDTLS, OPENSSL]
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
ssl: ["", MBEDTLS, OPENSSL]
select: ["-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0", "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0", "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=1"]
exclude:
- ssl: MBEDTLS
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
- ssl: MBEDTLS
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
- ssl: OPENSSL
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
- ssl: OPENSSL
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
env:
CC: ${{ matrix.cc }}
SSL: ${{ matrix.ssl }}
TFLAGS: ${{ matrix.select }}
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
@@ -54,7 +65,21 @@ jobs:
run: make unamalgamated && make valgrind && make mg_prefix
macos:
runs-on: macos-latest
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
strategy:
fail-fast: false
matrix:
ssl: ["", MBEDTLS, OPENSSL]
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
exclude:
- ssl: MBEDTLS
select: -DMG_ENABLE_POLL=0
- ssl: OPENSSL
select: -DMG_ENABLE_POLL=0
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
env:
SSL: ${{ matrix.ssl }}
TFLAGS: ${{ matrix.select }} -DNO_SNTP_CHECK
HOMEBREW_NO_AUTO_UPDATE: 1
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
@@ -62,27 +87,28 @@ jobs:
- if: ${{ env.GO == 1 }}
run: brew install jq mbedtls openssl
- if: ${{ env.GO == 1 }}
run: make test upload-coverage TFLAGS=-DNO_SNTP_CHECK SSL=OPENSSL ASAN_OPTIONS= OPENSSL=`echo /usr/local/Cellar/openssl*/*`
- if: ${{ env.GO == 1 }}
run: make test SSL=MBEDTLS TFLAGS=-DNO_SNTP_CHECK ASAN_OPTIONS= MBEDTLS=`echo /usr/local/Cellar/mbedtls*/*`
run: make test ASAN_OPTIONS= MBEDTLS=`echo /usr/local/Cellar/mbedtls*/*` OPENSSL=`echo /usr/local/Cellar/openssl*/*`
- if: ${{ env.GO == 1 }}
run: make mg_prefix
windows:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [vc98, vc17, vc22, mingw, mingw++]
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
exclude:
- target: vc98
select: -DMG_ENABLE_POLL=1
name: windows ${{ matrix.target }} TFLAGS=${{ matrix.select }}
env:
TFLAGS: ${{ matrix.select }}
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make vc98 vc17 vc22 mingw mingw++
arduino-xiao:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^examples/arduino|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make arduino-xiao
run: make ${{ matrix.target }}
arm:
runs-on: ubuntu-latest
steps:
@@ -99,8 +125,8 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: sudo apt -y install libmbedtls-dev libpcap-dev
- run: make clean examples
- run: make clean test MG_ENABLE_POLL=1
- run: make examples
- run: make clean
examples_win:
runs-on: windows-latest
steps:
@@ -122,25 +148,26 @@ jobs:
- run: make examples_mac
- run: make clean_examples_mac
test_f7:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f7" ; then echo GO=1 >> $GITHUB_ENV ; fi
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f7.*-make-" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-f746zg-freertos test VCON_API_KEY=${{secrets.VCON_API_KEY}}
run: make -C examples/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-f746zg-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 >> $GITHUB_ENV ; if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-f7.*-cube-'; then echo GO=1 >> $GITHUB_ENV ; fi
run: make -C examples/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 >> $GITHUB_ENV ; if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f7.*-cube-'; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
@@ -149,18 +176,18 @@ jobs:
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f4" ; then echo GO=1 >> $GITHUB_ENV ; fi
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f4.*-make-" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-f429zi-freertos test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 >> $GITHUB_ENV ; if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-f4.*-cube-'; then echo GO=1 >> $GITHUB_ENV ; fi
run: make -C examples/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 >> $GITHUB_ENV ; if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f4.*-cube-'; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
@@ -169,16 +196,44 @@ jobs:
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 3 }
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h7" ; then echo GO=1 >> $GITHUB_ENV ; fi
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h7.*-make-" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 >> $GITHUB_ENV ; if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-h7.*-cube-'; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
run: make -C examples/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 >> $GITHUB_ENV ; if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h7.*-cube-'; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
- if: ${{ env.GO == 1 }}
run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
test_h5:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 3 }
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h5.*-make-" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }}
run: make -C examples/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# - if: ${{ env.GO == 1 }}
# WIP run: make -C examples/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_rt1020:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 3 }
- run: if ./test/match_changed_files.sh "^src|examples/nxp/rt1020.*-make-" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }}
run: make -C examples/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- if: ${{ env.GO == 1 }}
run: make -C examples/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_tm4c:
runs-on: ubuntu-latest
@@ -188,13 +243,24 @@ jobs:
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/ti/ek-tm4c" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- run: echo GO=0 > $GITHUB_ENV ; if ./test/match_changed_files.sh "^src|examples/ti/ek-tm4c1294xl-baremetal" ; then echo GO=1 > $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C examples/ti/ek-tm4c1294xl-baremetal test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: echo GO=0 > $GITHUB_ENV ; if ./test/match_changed_files.sh "^src|examples/ti/ek-tm4c1294xl-freertos" ; then echo GO=1 > $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C examples/ti/ek-tm4c1294xl-freertos test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_same54:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/microchip/same54-xpro" ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update; sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }}
run: make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- if: ${{ env.GO == 1 }}
run: make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_pico_w5500:
runs-on: ubuntu-latest
steps:
@@ -206,6 +272,21 @@ jobs:
- if: ${{ env.GO == 1 }}
run: make -C examples/rp2040/pico-w5500 test VCON_API_KEY=${{secrets.VCON_API_KEY}}
arduino:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^examples/arduino|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C examples/arduino arduino-xiao
# - if: ${{ env.GO == 1 }}
# run: make -C examples/arduino arduino-nano
- if: ${{ env.GO == 1 }}
run: make -C examples/arduino clean
matrix_examples:
runs-on: ubuntu-latest
strategy:
@@ -215,14 +296,9 @@ jobs:
- path: esp32/device-dashboard
- path: esp32/uart-bridge
- path: esp8266/http-client-server
- path: stm32/nucleo-f429zi-make-baremetal-builtin
- path: stm32/nucleo-f429zi-freertos
- path: stm32/nucleo-f429zi-rndis
- path: stm32/nucleo-f746zg-make-baremetal-builtin
- path: stm32/nucleo-f746zg-freertos
- path: stm32/nucleo-f746zg-freertos-tcp
- path: stm32/nucleo-f746zg-rndis
- path: stm32/nucleo-h743zi-make-baremetal-builtin
- path: microchip/same54-xpro/device-dashboard
- path: microchip/same54-xpro/mqtt-client
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
- path: nxp/nxp-mimxrt1020-azurertos
- path: nxp/nxp-frdmk66f-freertos
- path: nxp/nxp-lpcxpresso54s018m-freertos
@@ -240,16 +316,29 @@ jobs:
- path: nxp/nxp-lpcxpresso54608-lwip-freertos
- path: nxp/nxp-lpcxpresso54618-lwip-freertos
- path: nxp/nxp-lpcxpresso54628-lwip-freertos
- path: nxp/rt1020-evk-make-baremetal-builtin
- path: nxp/rt1020-evk-make-freertos-builtin
- 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
- path: rp2040/pico-rmii
- path: rp2040/pico-rndis-dashboard
- path: rp2040/pico-w
- path: rp2040/pico-w5500
- path: stm32/nucleo-f429zi-make-baremetal-builtin
- path: stm32/nucleo-f429zi-make-freertos-builtin
- path: stm32/nucleo-f429zi-make-baremetal-builtin-rndis
- path: stm32/nucleo-f746zg-make-baremetal-builtin
- path: stm32/nucleo-f746zg-make-freertos-builtin
- path: stm32/nucleo-f746zg-make-freertos-tcp
- path: stm32/nucleo-f746zg-make-baremetal-builtin-rndis
- path: stm32/nucleo-g031-make-baremetal-builtin
- path: stm32/nucleo-h563zi-make-baremetal-builtin
- path: stm32/nucleo-h563zi-make-freertos-builtin
- path: stm32/nucleo-h743zi-make-baremetal-builtin
- path: stm32/nucleo-h743zi-make-freertos-builtin
- path: ti/ti-ek-tm4c1294xl-http-server
- path: ti/ek-tm4c1294xl-baremetal
- path: ti/ek-tm4c1294xl-freertos
name: ${{ matrix.example.path }}
steps:
- uses: actions/checkout@v3
+13 -34
View File
@@ -1,13 +1,14 @@
SRCS = mongoose.c test/unit_test.c test/packed_fs.c
HDRS = $(wildcard src/*.h) $(wildcard src/tcpip/*.h)
HDRS = $(wildcard src/*.h) $(wildcard src/drivers/*.h)
DEFS ?= -DMG_MAX_HTTP_HEADERS=7 -DMG_ENABLE_LINES -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_SSI=1 -DMG_ENABLE_ASSERT=1
WARN ?= -pedantic -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion -Wundef
OPTS ?= -O3 -g3
INCS ?= -Isrc -I.
SSL ?=
CWD ?= $(realpath $(CURDIR))
ENV ?= -e Tmp=. -e WINEDEBUG=-all
DOCKER ?= docker run --platform linux/amd64 --rm $(ENV) -v $(CWD):$(CWD) -w $(CWD)
ENV ?= -e Tmp=. -e WINEDEBUG=-all
DOCKER_BIN ?= docker
DOCKER ?= $(DOCKER_BIN) 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,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
@@ -36,13 +37,13 @@ endif
ifeq "$(SSL)" "MBEDTLS"
MBEDTLS ?= /usr/local
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
CFLAGS += -DMG_TLS=MG_TLS_MBED -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
CFLAGS += -DMG_TLS=MG_TLS_OPENSSL -I$(OPENSSL)/include
LDFLAGS += -L$(OPENSSL)/lib -lssl -lcrypto
endif
@@ -74,16 +75,9 @@ examples_win:
clean_examples_win:
$(foreach X, $(EXAMPLES_WIN), $(MAKE) -C $(X) clean &)
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/ca.pem
$(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 ?= packed_fs.c
mkfs:
$(CC) $(CFLAGS) test/pack.c -o pack
$(RUN) ./pack -s $(DIR) `find $(DIR) -type f` > $(OUT)
# find $(DIR) -type f | sed -e s,^$(DIR),,g -e s,^/,,g
$(RUN) ./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt test/data/ca.pem > $@
# Check that all external (exported) symbols have "mg_" prefix
mg_prefix: mongoose.c mongoose.h
@@ -95,7 +89,7 @@ musl: WARN += -Wno-sign-conversion
musl: CC = $(DOCKER) mdashnet/cc1 gcc
musl: RUN = $(DOCKER) mdashnet/cc1
# Make sure we can build from an unamalgamated sources
# Make sure we can build from unamalgamated sources.
unamalgamated: $(HDRS) Makefile test/packed_fs.c
$(CC) src/*.c test/packed_fs.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
@@ -161,21 +155,6 @@ 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
@@ -193,15 +172,15 @@ install: linux-libs
uninstall:
rm -rf $(DESTDIR)$(LIBDIR)/libmongoose.a $(DESTDIR)$(LIBDIR)/libmongoose.so.$(VERSION) $(DESTDIR)$(INCLUDEDIR)/mongoose.h $(DESTDIR)$(LIBDIR)/libmongoose.so
mongoose.c: Makefile $(wildcard src/*.c) $(wildcard src/tcpip/*.c)
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/tcpip/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
mongoose.c: Makefile $(wildcard src/*.c) $(wildcard src/drivers/*.c)
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/drivers/*.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/net_*.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.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 src/tcpip/tcpip.h src/tcpip/driver_*.h | sed -e '/keep/! 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_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.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 src/ota.h src/device.h src/net_builtin.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
clean: clean_examples clean_embedded
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
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
#find examples -maxdepth 3 -name zephyr -prune -o -name Makefile -print | xargs dirname | xargs -n1 make clean -C
clean_embedded:
+7 -6
View File
@@ -26,11 +26,12 @@ robust, and easy. Features include:
- Very easy to integrate: just copy `mongoose.c` and `mongoose.h` files to your source tree. See
[exact steps](https://mongoose.ws/documentation/#2-minute-integration-guide)
- Works with any network stack with socket API, like LwIP or FreeRTOS-Plus-TCP
- Provides a built-in TCP/IP stack with drivers for bare metal or RTOS systems
- A complete Web device dashboard
[bare metal example on Nucleo-F429ZI](examples/stm32/nucleo-f429zi-baremetal)
is only 6 files
- Built-in TCP/IP stack with drivers for bare metal or RTOS systems
- Available drivers: STM32 F4, F7, H5, H7; NXP RT1020; TI TM4C; Microchip SAME54; Wiznet W5500
- A complete Web device dashboard on bare metal
[Nucleo-F429ZI](examples/stm32/nucleo-f429zi-baremetal) is only 6 files
- For comparison, a CubeIDE generated HTTP example is 400+ files
- Built-in firmware updates for STM32H5, STM32H7, and more coming
- Detailed [user guide, API reference and tons of tutorials](https://mongoose.ws/documentation/) available
@@ -44,8 +45,8 @@ robust, and easy. Features include:
- See [Case Studies](https://mongoose.ws/case-studies/) from our respected
customers like [Schneider Electric](https://mongoose.ws/case-studies/schneider-electric/) (industrial automation), [Broadcom](https://mongoose.ws/case-studies/broadcom/) (semiconductors), [Pilz](https://mongoose.ws/case-studies/pilz/) (industrial automation), and others
- See [Testimonials](https://mongoose.ws/testimonials/) from engineers that integrated Mongoose in their commercial products
- We provide [Evaluation and Commercial licensing](https://mongoose.ws/licensing/), [support](https://mongoose.ws/support/), consultancy and integration
assistance - don't hesitate to [contact us](https://mongoose.ws/contact/)
- We provide [Evaluation and Commercial licensing](https://mongoose.ws/licensing/), [support](https://mongoose.ws/support/), consultancy and [integration
services](https://mongoose.ws/integration/) - don't hesitate to [contact us](https://mongoose.ws/contact/)
# Security
+28
View File
@@ -0,0 +1,28 @@
all:
example:
true
arduino: ENV = -v $(CWD):/root
arduino:
curl -sL http://downloads.arduino.cc/arduino-1.8.19-linux64.tar.xz | unxz | tar -xf -
mv arduino-* $@
arduino-xiao-board:
./arduino/arduino --pref "boardsmanager.additional.urls=https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json" --save-prefs
./arduino/arduino --pref "compiler.warning_level=all" --save-prefs
./arduino/arduino --install-boards Seeeduino:samd
arduino-xiao: arduino arduino-xiao-board
cd w5500-http && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 w5500-http.ino
cd w5500-mqtt && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 w5500-mqtt.ino
arduino-nano: arduino
cd w5500-http && ../arduino/arduino --pref compiler.cpp.extra_flags=-DMG_ENABLE_LOG=0 --verbose --verify --board arduino:avr:nano w5500-http.ino
cd w5500-mqtt && ../arduino/arduino --pref compiler.cpp.extra_flags=-DMG_ENABLE_LOG=0 --verbose --verify --board arduino:avr:nano w5500-mqtt.ino
clean:
rm -rf arduino
cleanall: clean #otherwise some parts of xiao-board installation will fail as already installed
rm -rf ~/.arduino15 ~/.oracle_jre_usage
File renamed without changes.
File renamed without changes.
@@ -11,4 +11,5 @@
#define MG_ENABLE_SOCKET 0
#define MG_ENABLE_TCPIP 1
#define mkdir(a, b) (-1)
#define MG_IO_SIZE 128
//#define MG_ENABLE_LOG 0
File renamed without changes.
@@ -0,0 +1,15 @@
#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_TCPIP 1
#define mkdir(a, b) (-1)
#define MG_IO_SIZE 512
//#define MG_ENABLE_LOG 0
+58
View File
@@ -0,0 +1,58 @@
#include "net.h"
#define MQTT_SERVER "mqtt://broker.hivemq.com:1883"
struct mg_connection *mqtt_connection;
const char *mqtt_subscribe_topic = "mg/rx";
const char *mqtt_publish_topic = "mg/tx";
struct mg_mgr mgr; // Mongoose event manager
struct mg_tcpip_if mif = {.mac = {2, 0, 1, 2, 3, 5}}; // network interface
void mqtt_publish(const char *message) {
struct mg_mqtt_opts opts = {};
opts.topic = mg_str(mqtt_publish_topic);
opts.message = mg_str(message);
if (mqtt_connection) mg_mqtt_pub(mqtt_connection, &opts);
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_MQTT_OPEN) {
MG_INFO(("%lu CONNECTED to %s", c->id, MQTT_SERVER));
struct mg_mqtt_opts opts = {};
opts.topic = mg_str(mqtt_subscribe_topic);
mg_mqtt_sub(c, &opts);
MG_INFO(("%lu SUBSCRIBED to %s", c->id, mqtt_subscribe_topic));
} else if (ev == MG_EV_MQTT_MSG) {
// Received MQTT message
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
MG_INFO(("%lu RECEIVED %.*s <- %.*s", c->id, (int) mm->data.len,
mm->data.ptr, (int) mm->topic.len, mm->topic.ptr));
exec_command(mm->data.ptr, mm->data.len);
} else if (ev == MG_EV_CLOSE) {
MG_INFO(("%lu CLOSED", c->id));
mqtt_connection = NULL;
}
}
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
struct mg_mqtt_opts opts;
memset(&opts, 0, sizeof(opts));
opts.clean = true;
if (mif.state == MG_TCPIP_STATE_READY && mqtt_connection == NULL) {
mqtt_connection = mg_mqtt_connect(mgr, MQTT_SERVER, &opts, fn, NULL);
}
// MG_INFO(("Eth: %d, MQTT: %p", mif.state, mqtt_connection));
}
void net_init(void) {
// Set Mongoose logging function to a serial print
mg_mgr_init(&mgr);
mif.driver = &mg_tcpip_driver_w5500;
mif.driver_data = &spi;
mg_tcpip_init(&mgr, &mif);
// Start a timer that keeps MQTT connection alive
mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT, timer_fn, &mgr);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "mongoose.h"
#ifdef __cplusplus
extern "C" {
#endif
extern struct mg_tcpip_spi spi;
extern struct mg_mgr mgr;
void mqtt_publish(const char *message);
void net_init(void);
void exec_command(const char *req, size_t req_len);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,51 @@
#include <SPI.h>
#include "net.h"
#define SS_PIN 17 // Slave select pin
struct mg_tcpip_spi spi = {
NULL, // SPI data
[](void *) { digitalWrite(SS_PIN, LOW); }, // Begin transaction
[](void *) { digitalWrite(SS_PIN, HIGH); }, // End transaction
[](void *, uint8_t c) { return SPI.transfer(c); }, // Execute transaction
};
void exec_command(const char *req, size_t req_len) {
char res[100];
if (req_len == 2 && strncmp(req, "on", req_len) == 0) {
digitalWrite(LED_BUILTIN, true);
snprintf(res, sizeof(res), "LED on");
} else if (req_len == 3 && strncmp(req, "off", req_len) == 0) {
digitalWrite(LED_BUILTIN, false);
snprintf(res, sizeof(res), "LED off");
} else {
snprintf(res, sizeof(res), "Unknown command: [%.*s]", (int) req_len, req);
}
Serial.println(res);
mqtt_publish(res);
}
static void process_input(char c) {
static char buf[100];
static size_t len = 0;
char response[100];
if (c != '\n' && c != '\0') buf[len++] = c; // Append to the buffer
if (len >= sizeof(buf)) len = 0; // On overflow, reset
if (c == '\n' && len > 0) {
exec_command(buf, len);
len = 0;
}
}
void setup() {
Serial.begin(115200);
SPI.begin();
pinMode(SS_PIN, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
net_init();
}
void loop() {
if (Serial.available()) process_input(Serial.read());
mg_mgr_poll(&mgr, 1);
}
+10 -6
View File
@@ -1,12 +1,13 @@
PROG ?= ./example # Program we are building
PACK ?= ./pack # Packing executable
DELETE = rm -rf # Command to remove files
GZIP ?= gzip # For compressing files in web_root/
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c net.c # Source code files
CFLAGS = -W -Wall -Wextra -g -I. # Build options
SOURCES = main.c mongoose.c net.c packed_fs.c # Source code files
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
CFLAGS_MONGOOSE +=
CFLAGS_MONGOOSE += -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG = example.exe # Use .exe suffix for the binary
@@ -14,6 +15,7 @@ ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To us
CC = gcc # Use MinGW gcc compiler
CFLAGS += -lws2_32 # Link against Winsock library
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
GZIP = echo # No gzip on Windows
endif
# Default target. Build and run program
@@ -33,15 +35,17 @@ web_root/main.css: web_root/index.html $(wildcard web_root/*.js)
npx tailwindcss -o $@ --minify
# Generate packed filesystem for serving Web UI
packed_fs.c: $(wildcard web_root/*) Makefile web_root/main.css web_root/bundle.js
packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile web_root/main.css web_root/bundle.js
$(GZIP) web_root/*
$(CC) ../../test/pack.c -o $(PACK)
$(PACK) $(wildcard web_root/*) > $@
$(PACK) web_root/* certs/* > $@
$(GZIP) -d web_root/*
mbedtls:
git clone --depth 1 -b v2.28.2 https://github.com/mbed-tls/mbedtls $@
ifeq ($(TLS), mbedtls)
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -Wno-conversion -Imbedtls/include
CFLAGS += -DMG_TLS=MG_TLS_MBED -Wno-conversion -Imbedtls/include
CFLAGS += -DMBEDTLS_CONFIG_FILE=\"mbedtls_config.h\" mbedtls/library/*.c
$(PROG): mbedtls
endif
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
@@ -0,0 +1,8 @@
-----BEGIN CERTIFICATE-----
MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X
DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT
BgcqhkjOPQIBBggqhkjOPQMBBwNCAARzSQS5OHd17lUeNI+6kp9WYu0cxuEIi/JT
jphbCmdJD1cUvhmzM9/phvJT9ka10Z9toZhgnBq0o0xfTQ4jC1vwMAoGCCqGSM49
BAMCA0gAMEUCIQCe0T2E0GOiVe9KwvIEPeX1J1J0T7TNacgR0Ya33HV9VgIgNvdn
aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=
-----END CERTIFICATE-----
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49
AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf
6YbyU/ZGtdGfbaGYYJwatKNMX00OIwtb8A==
-----END EC PRIVATE KEY-----
-1
View File
@@ -17,7 +17,6 @@ int main(void) {
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
srand(time(NULL));
mg_log_set(MG_LL_DEBUG); // Set debug log level
mg_mgr_init(&mgr);
+3 -2
View File
@@ -6,6 +6,7 @@
#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#define MBEDTLS_HAVE_TIME
#define MBEDTLS_SSL_SESSION_TICKETS
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
@@ -51,8 +52,9 @@
#define MBEDTLS_AES_FEWER_TABLES
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_BASE64_C
#define MBEDTLS_SSL_TICKET_C
// TLS 1.2
#define MBEDTLS_SSL_PROTO_TLS1_3
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_GCM_C
@@ -60,4 +62,3 @@
#define MBEDTLS_ECP_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ASN1_WRITE_C
+95 -49
View File
@@ -28,45 +28,24 @@ static const char *s_json_header =
"Cache-Control: no-cache\r\n";
static uint64_t s_boot_timestamp = 0; // Updated by SNTP
// Certificate generation procedure:
// openssl ecparam -name prime256v1 -genkey -noout -out key.pem
// openssl req -new -key key.pem -x509 -nodes -days 3650 -out cert.pem
static const char *s_ssl_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X\n"
"DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT\n"
"BgcqhkjOPQIBBggqhkjOPQMBBwNCAARzSQS5OHd17lUeNI+6kp9WYu0cxuEIi/JT\n"
"jphbCmdJD1cUvhmzM9/phvJT9ka10Z9toZhgnBq0o0xfTQ4jC1vwMAoGCCqGSM49\n"
"BAMCA0gAMEUCIQCe0T2E0GOiVe9KwvIEPeX1J1J0T7TNacgR0Ya33HV9VgIgNvdn\n"
"aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=\n"
"-----END CERTIFICATE-----\n";
static const char *s_ssl_key =
"-----BEGIN EC PRIVATE KEY-----\n"
"MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49\n"
"AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf\n"
"6YbyU/ZGtdGfbaGYYJwatKNMX00OIwtb8A==\n"
"-----END EC PRIVATE KEY-----\n";
// This is for newlib and TLS (mbedTLS)
uint64_t mg_now(void) {
return mg_millis() + s_boot_timestamp;
}
int ui_event_next(int no, struct ui_event *e) {
if (no < 0 || no >= MAX_EVENTS_NO)
return 0;
if (no < 0 || no >= MAX_EVENTS_NO) return 0;
srand(no);
srand((unsigned) no);
e->type = (uint8_t) rand() % 4;
e->prio = (uint8_t) rand() % 3;
e->timestamp = (unsigned long) (mg_now() - 86400 * 1000 /* one day back */ +
no * 300 * 1000 /* 5 mins between alerts */ +
1000 * (rand() % 300) /* randomize event time */) /
1000;
mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE,
"event#%d", no);
e->timestamp =
(unsigned long) ((int64_t) mg_now() - 86400 * 1000 /* one day back */ +
no * 300 * 1000 /* 5 mins between alerts */ +
1000 * (rand() % 300) /* randomize event time */) /
1000UL;
mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, "event#%d", no);
return no + 1;
}
@@ -104,7 +83,7 @@ static struct user *authenticate(struct mg_http_message *hm) {
char user[64], pass[64];
struct user *u, *result = NULL;
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
MG_INFO(("user [%s] pass [%s]", user, pass));
MG_VERBOSE(("user [%s] pass [%s]", user, pass));
if (user[0] != '\0' && pass[0] != '\0') {
// Both user and password is set, search by user/password
@@ -164,23 +143,24 @@ static void handle_stats_get(struct mg_connection *c) {
static size_t print_events(void (*out)(char, void *), void *ptr, va_list *ap) {
size_t len = 0;
struct ui_event ev;
int pageno = va_arg(*ap, unsigned);
int pageno = va_arg(*ap, int);
int no = (pageno - 1) * EVENTS_PER_PAGE;
int end = no + EVENTS_PER_PAGE;
while ((no = ui_event_next(no, &ev)) != 0 && no <= end) {
len += mg_xprintf(out, ptr, "%s{%m:%lu,%m:%d,%m:%d,%m:%m}", //
len == 0 ? "" : ",", //
MG_ESC("time"), ev.timestamp, //
MG_ESC("type"), ev.type, //
MG_ESC("prio"), ev.prio, //
MG_ESC("time"), ev.timestamp, //
MG_ESC("type"), ev.type, //
MG_ESC("prio"), ev.prio, //
MG_ESC("text"), MG_ESC(ev.text));
}
return len;
}
static void handle_events_get(struct mg_connection *c, struct mg_http_message *hm) {
static void handle_events_get(struct mg_connection *c,
struct mg_http_message *hm) {
int pageno = mg_json_get_long(hm->body, "$.page", 1);
mg_http_reply(c, 200, s_json_header, "{%m:[%M], %m:%d}", MG_ESC("arr"),
print_events, pageno, MG_ESC("totalCount"), MAX_EVENTS_NO);
@@ -218,11 +198,72 @@ static void handle_settings_get(struct mg_connection *c) {
MG_ESC("device_name"), MG_ESC(s_settings.device_name));
}
static void handle_firmware_upload(struct mg_connection *c,
struct mg_http_message *hm) {
char name[64], offset[20], total[20];
struct mg_str data = hm->body;
long ofs = -1, tot = -1;
name[0] = offset[0] = '\0';
mg_http_get_var(&hm->query, "name", name, sizeof(name));
mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
mg_http_get_var(&hm->query, "total", total, sizeof(total));
MG_INFO(("File %s, offset %s, len %lu", name, offset, data.len));
if ((ofs = mg_json_get_long(mg_str(offset), "$", -1)) < 0 ||
(tot = mg_json_get_long(mg_str(total), "$", -1)) < 0) {
mg_http_reply(c, 500, "", "offset and total not set\n");
} else if (ofs == 0 && mg_ota_begin((size_t) tot) == false) {
mg_http_reply(c, 500, "", "mg_ota_begin(%ld) failed\n", tot);
} else if (data.len > 0 && mg_ota_write(data.ptr, data.len) == false) {
mg_http_reply(c, 500, "", "mg_ota_write(%lu) @%ld failed\n", data.len, ofs);
mg_ota_end();
} else if (data.len == 0 && mg_ota_end() == false) {
mg_http_reply(c, 500, "", "mg_ota_end() failed\n", tot);
} else {
mg_http_reply(c, 200, s_json_header, "true\n");
if (data.len == 0) {
// Successful mg_ota_end() called, schedule device reboot
mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_device_reset, NULL);
}
}
}
static void handle_firmware_commit(struct mg_connection *c) {
mg_http_reply(c, 200, s_json_header, "%s\n",
mg_ota_commit() ? "true" : "false");
}
static void handle_firmware_rollback(struct mg_connection *c) {
mg_http_reply(c, 200, s_json_header, "%s\n",
mg_ota_rollback() ? "true" : "false");
}
static size_t print_status(void (*out)(char, void *), void *ptr, va_list *ap) {
int fw = va_arg(*ap, int);
return mg_xprintf(out, ptr, "{%m:%d,%m:%c%lx%c,%m:%u,%m:%u}",
MG_ESC("status"), mg_ota_status(fw), MG_ESC("crc32"), '"',
mg_ota_crc32(fw), '"', MG_ESC("size"), mg_ota_size(fw),
MG_ESC("timestamp"), mg_ota_timestamp(fw));
}
static void handle_firmware_status(struct mg_connection *c) {
mg_http_reply(c, 200, s_json_header, "[%M,%M]\n", print_status,
MG_FIRMWARE_CURRENT, print_status, MG_FIRMWARE_PREVIOUS);
}
static void handle_device_reset(struct mg_connection *c) {
mg_http_reply(c, 200, s_json_header, "true\n");
mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_device_reset, NULL);
}
// HTTP request handler function
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_ACCEPT && fn_data != NULL) {
struct mg_tls_opts opts = {.cert = s_ssl_cert, .certkey = s_ssl_key};
mg_tls_init(c, &opts);
if (ev == MG_EV_ACCEPT) {
if (fn_data != NULL) { // TLS listener!
struct mg_tls_opts opts = {0};
opts.cert = mg_unpacked("/certs/server_cert.pem");
opts.key = mg_unpacked("/certs/server_key.pem");
mg_tls_init(c, &opts);
}
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct user *u = authenticate(hm);
@@ -243,14 +284,24 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
handle_settings_get(c);
} else if (mg_http_match_uri(hm, "/api/settings/set")) {
handle_settings_set(c, hm->body);
} else if (mg_http_match_uri(hm, "/api/firmware/upload")) {
handle_firmware_upload(c, hm);
} else if (mg_http_match_uri(hm, "/api/firmware/commit")) {
handle_firmware_commit(c);
} else if (mg_http_match_uri(hm, "/api/firmware/rollback")) {
handle_firmware_rollback(c);
} else if (mg_http_match_uri(hm, "/api/firmware/status")) {
handle_firmware_status(c);
} else if (mg_http_match_uri(hm, "/api/device/reset")) {
handle_device_reset(c);
} else {
struct mg_http_serve_opts opts;
memset(&opts, 0, sizeof(opts));
#if MG_ENABLE_PACKED_FS
opts.root_dir = "/web_root";
opts.fs = &mg_fs_packed;
#if MG_ARCH == MG_ARCH_UNIX || MG_ARCH == MG_ARCH_WIN32
opts.root_dir = "web_root"; // On workstations, use filesystem
#else
opts.root_dir = "web_root";
opts.root_dir = "/web_root"; // On embedded, use packed files
opts.fs = &mg_fs_packed;
#endif
mg_http_serve_dir(c, ev_data, &opts);
}
@@ -262,13 +313,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
void web_init(struct mg_mgr *mgr) {
s_settings.device_name = strdup("My Device");
mg_http_listen(mgr, HTTP_URL, fn, NULL);
#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL
mg_http_listen(mgr, HTTPS_URL, fn, "");
#endif
// mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_mqtt_fn, c->mgr);
mg_http_listen(mgr, HTTPS_URL, fn, (void *) 1);
mg_timer_add(mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT,
timer_sntp_fn, mgr);
}
+1 -1
View File
@@ -9,7 +9,7 @@
#endif
#if !defined(HTTPS_URL)
#define HTTPS_URL "http://0.0.0.0:8443"
#define HTTPS_URL "https://0.0.0.0:8443"
#endif
#define MAX_DEVICE_NAME 40
File diff suppressed because it is too large. Load diff
+121 -27
View File
@@ -1,11 +1,16 @@
'use strict';
import { h, render, useState, useEffect, useRef, html, Router } from './bundle.js';
// Helper function that returns a promise that resolves after delay
const Delay = (ms, val) => new Promise(resolve => setTimeout(resolve, ms, val));
export const Icons = {
heart: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>`,
downArrowBox: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15M9 12l3 3m0 0l3-3m-3 3V2.25" /> </svg>`,
upArrowBox: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15" /> </svg>`,
settings: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>`,
cog: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>`,
settingsH: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" /> </svg>`,
settingsV: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6 13.5V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m12-3V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m-6-9V3.75m0 3.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 9.75V10.5" /> </svg>`,
scan: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 3.75H6A2.25 2.25 0 003.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0120.25 6v1.5m0 9V18A2.25 2.25 0 0118 20.25h-1.5m-9 0H6A2.25 2.25 0 013.75 18v-1.5M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg> `,
desktop: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25" /> </svg>`,
alert: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5" /> </svg>`,
@@ -31,13 +36,18 @@ export const Icons = {
arrowup: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 19.5v-15m0 0l-6.75 6.75M12 4.5l6.75 6.75" /> </svg>`,
warn: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`,
info: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" /> </svg>`,
exclamationTriangle: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`
exclamationTriangle: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`,
thumbUp: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z" /> </svg>`,
backward: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M21 16.811c0 .864-.933 1.405-1.683.977l-7.108-4.062a1.125 1.125 0 010-1.953l7.108-4.062A1.125 1.125 0 0121 8.688v8.123zM11.25 16.811c0 .864-.933 1.405-1.683.977l-7.108-4.062a1.125 1.125 0 010-1.953L9.567 7.71a1.125 1.125 0 011.683.977v8.123z" /> </svg>`,
chip: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21m-9-1.5h10.5a2.25 2.25 0 002.25-2.25V6.75a2.25 2.25 0 00-2.25-2.25H6.75A2.25 2.25 0 004.5 6.75v10.5a2.25 2.25 0 002.25 2.25zm.75-12h9v9h-9v-9z" /> </svg>`,
camera: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6.827 6.175A2.31 2.31 0 015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM18.75 10.5h.008v.008h-.008V10.5z" /> </svg>`,
arrows: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" /> </svg>`,
};
export const tipColors = {
green: 'bg-green-100 text-green-900',
yellow: 'bg-yellow-100 text-yellow-900',
red: 'bg-red-100 text-red-900',
green: 'bg-green-100 text-green-900 ring-green-300',
yellow: 'bg-yellow-100 text-yellow-900 ring-yellow-300',
red: 'bg-red-100 text-red-900 ring-red-300',
};
export function Button({title, onclick, disabled, cls, icon, ref, colors, hovercolor, disabledcolor}) {
@@ -51,7 +61,7 @@ export function Button({title, onclick, disabled, cls, icon, ref, colors, hoverc
};
if (!colors) colors = 'bg-blue-600 hover:bg-blue-500 disabled:bg-blue-400';
return html`
<button type="button" class="inline-flex justify-center items-center gap-1 rounded px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm ${colors} ${cls}"
<button type="button" class="inline-flex justify-center items-center gap-2 rounded px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm ${colors} ${cls}"
ref=${ref} onclick=${cb} disabled=${disabled || spin} >
${title}
<${spin ? Icons.refresh : icon} class="w-4 ${spin ? 'animate-spin' : ''}" />
@@ -136,25 +146,26 @@ export function Login({loginFn, logoIcon, title, tipText}) {
};
export function Colored({icon, text, colors}) {
colors ||= 'bg-slate-100 text-slate-900';
return html`
<span class="inline-flex items-center gap-1.5 py-0.5 px-2 rounded-full ${colors || 'bg-slate-100 text-slate-900'}">
<span class="inline-flex items-center gap-1.5 py-0.5">
${icon && html`<${icon} class="w-5 h-5" />`}
<span class="inline-block text-xs font-medium">${text}<//>
<span class="inline-block font-medium rounded-md px-2 py-1 text-xs ring-1 ring-inset ${colors}">${text}<//>
<//>`;
};
export function Stat({title, text, tipText, tipIcon, tipColors}) {
export function Stat({title, text, tipText, tipIcon, tipColors, colors}) {
return html`
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-slate-900 dark:border-gray-800">
<div class="p-4 md:p-5">
<div class="overflow-auto rounded-lg bg-white px-4 py-2 shadow">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500"> ${title} </p>
<p class="text-sm truncate text-gray-500 font-medium"> ${title} </p>
<//>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-gray-200">
<h3 class="text-xl truncate font-semibold tracking-tight ${colors || 'text-gray-800 dark:text-gray-200'}">
${text}
<//>
<span class="flex items-center">
<span class="flex items-center ${tipText || 'hidden'}">
<${Colored} text=${tipText} icon=${tipIcon} colors=${tipColors} />
<//>
<//>
@@ -162,15 +173,27 @@ export function Stat({title, text, tipText, tipIcon, tipColors}) {
<//>`;
};
export function TextValue({value, setfn, disabled, placeholder, type, addonRight, addonLeft, attr}) {
const f = type == 'number' ? x => setfn(parseInt(x)) : setfn;
export function TextValue({value, setfn, disabled, placeholder, type, addonRight, addonLeft, attr, min, max, step}) {
const [bg, setBg] = useState('bg-white');
useEffect(() => { checkval(value); }, []);
const checkval = function(v) {
setBg('bg-white');
if (min && v < min) setBg('bg-red-100 border-red-200');
if (max && v > max) setBg('bg-red-100 border-red-200');
};
const oninput = ev => {
let v = ev.target.value;
if (type == 'number') v = parseInt(v);
setfn(v);
checkval(v);
};
return html`
<div class="flex w-full items-center rounded border shadow-sm">
${ addonLeft && html`<span class="inline-flex font-normal truncate py-1 border-r bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs">${addonLeft}</>` }
<div class="flex w-full items-center rounded border shadow-sm ${bg}">
${ addonLeft && html`<span class="inline-flex font-normal truncate py-1 border-r bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs">${addonLeft}<//>` }
<input type=${type || 'text'} disabled=${disabled}
oninput=${ev => f(ev.target.value)} ...${attr}
class="font-normal text-sm rounded w-full flex-1 py-0.5 px-2 text-gray-700 placeholder:text-gray-400 focus:outline-none disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-500" placeholder=${placeholder} value=${value} />
${ addonRight && html`<span class="inline-flex font-normal truncate py-1 border-l bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs">${addonRight}</>` }
oninput=${oninput} ...${attr}
class="${bg} font-normal text-sm rounded w-full flex-1 py-0.5 px-2 text-gray-700 placeholder:text-gray-400 focus:outline-none disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-500" placeholder=${placeholder} value=${value} />
${ addonRight && html`<span class="inline-flex font-normal truncate py-1 border-l bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs overflow-scroll" style="min-width: 50%;">${addonRight}<//>` }
<//>`;
};
@@ -194,29 +217,29 @@ export function SwitchValue({value, setfn}) {
};
export function Setting(props) {
let input = TextValue;
if (props.type == 'switch') input = SwitchValue;
if (props.type == 'select') input = SelectValue;
return html`
<div class=${props.cls || 'grid grid-cols-2 gap-2 my-1'}>
<label class="flex items-center text-sm text-gray-700 mr-2 font-medium">${props.title}<//>
<div class="flex items-center">
${props.type == 'switch' ? h(SwitchValue, props) :
props.type == 'select' ? h(SelectValue, props) :
h(TextValue, props) }
<//>
<div class="flex items-center">${h(input, props)}<//>
<//>`;
};
export function Pagination({ totalItems, itemsPerPage, currentPage, setPageFn }) {
export function Pagination({ totalItems, itemsPerPage, currentPage, setPageFn, colors }) {
const totalPages = Math.ceil(totalItems / itemsPerPage);
const maxPageRange = 2;
const lessThanSymbol = "<";
const greaterThanSymbol = ">";
const whiteSpace = " ";
const itemcls = 'relative inline-flex items-center px-3 py-1 text-sm focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-0 focus-visible:outline-blue-600';
colors ||= 'bg-blue-600';
const PageItem = ({ page, isActive }) => (
html`<a
onClick=${() => setPageFn(page)}
class="${itemcls} ${isActive ? 'bg-blue-600 text-white' : 'cursor-pointer text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50'}"
class="${itemcls} ${isActive ? `${colors} text-white` : 'cursor-pointer text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50'}"
>
${page}
</a>`
@@ -253,3 +276,74 @@ export function Pagination({ totalItems, itemsPerPage, currentPage, setPageFn })
</div>
</div>`;
};
export function UploadFileButton(props) {
const [upload, setUpload] = useState(null); // Upload promise
const [status, setStatus] = useState(''); // Current upload status
const btn = useRef(null);
const input = useRef(null);
// Send a large file chunk by chunk
const sendFileData = function(url, fileName, fileData, chunkSize) {
return new Promise(function(resolve, reject) {
const finish = ok => {
setUpload(null);
const res = props.onupload ? props.onupload(ok, fileName, fileData.length) : null;
if (res && typeof (res.catch) === 'function') {
res.catch(() => false).then(() => ok ? resolve() : reject());
} else {
ok ? resolve() : reject();
}
};
const sendChunk = function(offset) {
var chunk = fileData.subarray(offset, offset + chunkSize) || '';
var opts = {method: 'POST', body: chunk};
var fullUrl = url + '?offset=' + offset +
'&total=' + fileData.length +
'&name=' + encodeURIComponent(fileName);
var ok;
setStatus('Uploading ' + fileName + ', bytes ' + offset + '..' +
(offset + chunk.length) + ' of ' + fileData.length);
fetch(fullUrl, opts)
.then(function(res) {
if (res.ok && chunk.length > 0) sendChunk(offset + chunk.length);
ok = res.ok;
return res.text();
})
.then(function(text) {
if (!ok) setStatus('Error: ' + text), finish(ok); // Fail
if (chunk.length > 0) return; // More chunks to send
setStatus(x => x + '. Done, resetting device...');
finish(ok); // All chunks sent
});
};
//setFailed(false);
sendChunk(0);
});
};
const onchange = function(ev) {
if (!ev.target.files[0]) return;
let r = new FileReader(), f = ev.target.files[0];
r.readAsArrayBuffer(f);
r.onload = function() {
setUpload(sendFileData(props.url, f.name, new Uint8Array(r.result), 2048));
ev.target.value = '';
ev.preventDefault();
btn && btn.current.base.click();
};
};
const onclick = function(ev) {
let fn; setUpload(x => fn = x);
if (!fn) input.current.click(); // No upload in progress, show file dialog
return fn;
};
return html`
<div class="inline-flex flex-col ${props.class}">
<input class="hidden" type="file" ref=${input} onchange=${onchange} accept=${props.accept} />
<${Button} title=${props.title} icon=${Icons.download} onclick=${onclick} ref=${btn} colors=${props.colors} />
<div class="py-2 text-sm text-slate-400 ${status || 'hidden'}">${status}<//>
<//>`;
};
+1 -1
View File
@@ -1 +1 @@
/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter var,Helvetica,sans-serif;font-feature-settings:"cv11","ss01";font-variation-settings:"opsz" 32}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.left-0{left:0}.right-auto{right:auto}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.col-span-2{grid-column:span 2/span 2}.m-4{margin:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.mb-1{margin-bottom:.25rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-7{margin-top:1.75rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-0{width:0}.w-11{width:2.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-96{width:24rem}.w-full{width:100%}.min-w-full{min-width:100%}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow-0{flex-grow:0}.basis-\[30px\]{flex-basis:30px}.border-separate{border-collapse:initial}.border-spacing-0{--tw-border-spaciLine truncated
/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter var,Helvetica,sans-serif;font-feature-settings:"cv11","ss01";font-variation-settings:"opsz" 32}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.left-0{left:0}.right-4{right:1rem}.right-auto{right:auto}.top-0{top:0}.top-4{top:1rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.col-span-2{grid-column:span 2/span 2}.m-4{margin:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.mb-1{margin-bottom:.25rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-7{margin-top:1.75rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-0{width:0}.w-11{width:2.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-96{width:24rem}.w-full{width:100%}.min-w-full{min-width:100%}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow-0{flex-grow:0}.basis-\[30px\]{flex-basis:30px}.border-separate{border-collapse:initialLine truncated
+105 -7
View File
@@ -2,7 +2,7 @@
'use strict';
import { h, render, useState, useEffect, useRef, html, Router } from './bundle.js';
import { Icons, Login, Setting, Button, Stat, tipColors, Colored, Notification, Pagination } from './components.js';
import { Icons, Login, Setting, Button, Stat, tipColors, Colored, Notification, Pagination, UploadFileButton } from './components.js';
const Logo = props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12.87 12.85"><defs><style>.ll-cls-1{fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:0.5px;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="ll-cls-1" d="M12.62,1.82V8.91A1.58,1.58,0,0,1,11,10.48H4a1.44,1.44,0,0,1-1-.37A.69.69,0,0,1,2.84,10l-.1-.12a.81.81,0,0,1-.15-.48V5.57a.87.87,0,0,1,.86-.86H4.73V7.28a.86.86,0,0,0,.86.85H9.42a.85.85,0,0,0,.85-.85V3.45A.86.86,0,0,0,10.13,3,.76.76,0,0,0,10,2.84a.29.29,0,0,0-.12-.1,1.49,1.49,0,0,0-1-.37H2.39V1.82A1.57,1.57,0,0,1,4,.25H11A1.57,1.57,0,0,1,12.62,1.82Z"/><path class="ll-cls-1" d="M10.48,10.48V11A1.58,1.58,0,0,1,8.9,12.6H1.82A1.57,1.57,0,0,1,.25,11V3.94A1.57,1.57,0,0,1,1.82,2.37H8.9a1.49,1.49,0,0,1,1,.37l.12.1a.76.76,0,0,1,.11.14.86.86,0,0,1,.14.47V7.28a.85.85,0,0,1-.85.85H8.13V5.57a.86.86,0,0,0-.85-.86H3.45a.87.87,0,0,0-.86.86V9.4a.81.81,0,0,0,.15.48l.1.12a.69.69,0,0,0,.13.11,1.44,1.44,0,0,0,1,.37Z"/></g></g></svg>`;
@@ -45,7 +45,8 @@ function Sidebar({url, show}) {
<//>
<div class="flex flex-1 flex-col">
<${NavLink} title="Dashboard" icon=${Icons.home} href="/" url=${url} />
<${NavLink} title="Settings" icon=${Icons.settings} href="/settings" url=${url} />
<${NavLink} title="Settings" icon=${Icons.cog} href="/settings" url=${url} />
<${NavLink} title="Firmware Update" icon=${Icons.download} href="/update" url=${url} />
<${NavLink} title="Events" icon=${Icons.alert} href="/events" url=${url} />
<//>
<//>
@@ -143,13 +144,16 @@ function Chart({data}) {
<//>`;
};
function DeveloperNote({text}) {
function DeveloperNote({text, children}) {
return html`
<div class="flex p-4 gap-2">
<${Icons.info} class="self-start basis-[30px] grow-0 shrink-0 text-green-600" />
<div class="text-sm">
<div class="font-semibold mt-1">Developer Note<//>
${text.split('.').map(v => html` <p class="my-2 text-slate-500">${v}<//>`)}
<div class="text-sm text-slate-500">
<div class="flex items-center">
<${Icons.info} class="self-start basis-[30px] grow-0 shrink-0 text-green-600 mr-2" />
<div class="font-semibold">Developer Note<//>
<//>
${(text || '').split('.').map(v => html` <p class="my-2 ">${v}<//>`)}
${children}
<//>
<//>`;
};
@@ -181,6 +185,99 @@ function Main({}) {
<//>`;
};
function FirmwareStatus({title, info, children}) {
const state = ['UNAVAILABLE', 'FIRST_BOOT', 'NOT_COMMITTED', 'COMMITTED'][(info.status || 0) % 4];
const valid = info.status > 0;
return html`
<div class="bg-white py-1 divide-y border rounded">
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
${title}
<//>
<div class="px-4 py-2 relative">
<div class="my-1">Status: ${state}<//>
<div class="my-1">CRC32: ${valid ? info.crc32.toString(16) : 'n/a'}<//>
<div class="my-1">Size: ${valid ? info.size : 'n/a'}<//>
<div class="my-1">Flashed at: ${valid ? new Date(info.timestamp * 1000).toLocaleString() : 'n/a'}<//>
${children}
<//>
<//>`;
};
function FirmwareUpdate({}) {
const [info, setInfo] = useState([{}, {}]);
const refresh = () => fetch('api/firmware/status').then(r => r.json()).then(r => setInfo(r));
useEffect(refresh, []);
const oncommit = ev => fetch('api/firmware/commit')
.then(r => r.json())
.then(refresh);
const onreboot = ev => fetch('api/device/reset')
.then(r => r.json())
.then(r => new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000)));
const onrollback = ev => fetch('api/firmware/rollback')
.then(onreboot);
const onupload = function(ok, name, size) {
if (!ok) return false;
return new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000));
};
const clean = info[0].valid && info[0].golden == 0;
return html`
<div class="m-4 gap-4 grid grid-cols-1 lg:grid-cols-2">
<${FirmwareStatus} title="Current firmware image" info=${info[0]}>
<div class="flex flex-wrap gap-2">
<${Button} title="Commit this firmware"
onclick=${oncommit} icon=${Icons.thumbUp} disabled=${clean} />
<${Button} title="Reboot device" onclick=${onreboot} icon=${Icons.refresh} clsx="absolute top-4 right-4" />
<${UploadFileButton}
title="Upload new firmware: choose .bin file:" onupload=${onupload}
url="api/firmware/upload" accept=".bin,.uf2" />
<//>
<//>
<${FirmwareStatus} title="Previous firmware image" info=${info[1]}>
<${Button} title="Rollback to this firmware" onclick=${onrollback}
icon=${Icons.backward} disabled=${info[1].valid == false} />
<//>
<div class="bg-white border shadow-lg">
<${DeveloperNote}>
<div class="my-2">
When a new firmware gets flashed, its status is marked as, "first_boot".
That is an unreliable (uncommitted) firmware. A user may choose
to revert back to the previous committed firmware on the subsequent
boots. Clicking on the "commit" button calls "mg_ota_commit()" function
which commits the firmware.
<//>
<div class="my-2">
This GUI loads a firmware file and sends it chunk by chunk to the
device, passing current chunk offset, total firmware size and a file name:
api/firmware/upload?offset=X&total=Y&name=Z
<//>
<//>
<//>
<div class="bg-white border shadow-lg">
<${DeveloperNote}>
<div>
Firmware update mechanism defines 3 API functions that the target
device must implement: mg_ota_begin(), mg_ota_write() and mg_ota_end()
<//>
<div class="my-2">
RESTful API handlers use ota_xxx() API to save firmware to flash.
The last 0-length chunk triggers ota_end() which performs firmware
update using saved firmware image
<//>
<div class="my-2">
<a class="link text-blue-600 underline"
href="https://mongoose.ws/webinars/">Join our free webinar</a> to
get detailed explanations about possible firmware updates strategies
and implementation demo
<//>
<//>
<//>
<//>`;
};
function Settings({}) {
const [settings, setSettings] = useState(null);
const [saveResult, setSaveResult] = useState(null);
@@ -256,6 +353,7 @@ const App = function({}) {
<${Router} onChange=${ev => setUrl(ev.url)} history=${History.createHashHistory()} >
<${Main} default=${true} />
<${Settings} path="settings" />
<${FirmwareUpdate} path="update" />
<${Events} path="events" />
<//>
<//>
+58 -696
View File
@@ -2,553 +2,61 @@
#include <string.h>
#include <time.h>
#if defined(__cplusplus)
extern "C" {
#endif
const char *mg_unlist(size_t no);
const char *mg_unpack(const char *, size_t *, time_t *);
#if defined(__cplusplus)
}
#endif
static const unsigned char v1[] = {
31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 112, 114, // .......b..pr
101, 97, 99, 116, 46, 109, 105, 110, 46, 106, 115, 0, // eact.min.js.
157, 91, 123, 119, 219, 182, 146, 255, 127, 63, 69, 164, // .[{w.....?E.
211, 163, 18, 43, 68, 177, 147, 182, 187, 75, 5, 213, // ...+D....K..
105, 29, 183, 238, 109, 234, 230, 38, 105, 123, 123, 85, // i...m..&i{{U
93, 30, 138, 132, 44, 214, 20, 169, 242, 97, 91, 53, // ]...,....a[5
245, 221, 247, 55, 3, 128, 164, 108, 185, 247, 236, 158, // ...7...l....
36, 34, 30, 131, 1, 48, 47, 204, 12, 144, 155, 176, // $"...0/.....
120, 166, 101, 38, 3, 89, 201, 92, 22, 178, 150, 169, // x.e&.Y......
186, 223, 203, 68, 205, 23, 50, 82, 47, 194, 40, 169, // ...D..2R/.(.
26, 125, 231, 205, 252, 178, 185, 106, 178, 102, 219, 124, // .}.....j.f.|
34, 154, 98, 187, 110, 174, 138, 36, 110, 242, 219, 178, // ".b.n..$n...
217, 100, 81, 147, 85, 183, 77, 146, 233, 121, 180, 94, // .dQ.U.M..y.^
52, 127, 230, 121, 243, 175, 188, 136, 155, 164, 210, 69, // 4..y.......E
248, 34, 153, 174, 234, 44, 170, 146, 60, 123, 86, 122, // ."...,..<{Vz
152, 72, 220, 175, 242, 194, 187, 193, 172, 193, 179, 36, // .H.........$
123, 150, 9, 61, 15, 22, 42, 195, 207, 180, 208, 85, // {..=..*....U
93, 100, 207, 244, 190, 29, 177, 242, 180, 184, 39, 216, // ]d........'.
76, 233, 201, 54, 44, 116, 86, 93, 230, 177, 158, 102, // L..6,tV]...f
163, 81, 54, 41, 244, 38, 191, 209, 103, 235, 36, 141, // .Q6).&..g.$.
1, 214, 13, 10, 61, 222, 141, 25, 216, 109, 105, 74, // ....=....miJ
243, 214, 52, 103, 32, 134, 215, 122, 55, 84, 170, 158, // ..4g ..z7T..
229, 42, 152, 215, 11, 127, 88, 232, 21, 215, 11, 83, // .*....X....S
79, 241, 195, 165, 105, 178, 242, 194, 226, 170, 222, 96, // O...i......`
230, 114, 146, 234, 236, 170, 90, 127, 249, 114, 52, 242, // .r....Z..r4.
210, 73, 68, 19, 99, 69, 234, 81, 255, 171, 153, 158, // .ID.cE.Q....
68, 97, 154, 118, 35, 229, 75, 225, 87, 66, 14, 221, // Da.v#.K.WB..
26, 49, 87, 181, 219, 234, 124, 245, 140, 118, 82, 167, // .1W...|..vR.
233, 64, 101, 147, 88, 175, 194, 58, 173, 222, 21, 249, // .@e.X..:....
182, 20, 237, 98, 31, 180, 223, 228, 73, 252, 236, 68, // ...b....I..D
41, 69, 75, 164, 117, 208, 74, 15, 97, 208, 34, 28, // )EK.u.J.a.".
45, 183, 160, 69, 202, 124, 165, 89, 122, 68, 218, 130, // -..E.|.YzD..
23, 150, 225, 134, 80, 32, 17, 45, 201, 215, 114, 75, // ....P .-..rK
72, 252, 74, 130, 70, 62, 0, 244, 202, 47, 100, 16, // H.J.F>.../d.
92, 251, 132, 1, 5, 247, 93, 250, 39, 248, 213, 174, // ......].'...
26, 251, 102, 105, 40, 70, 174, 109, 109, 10, 81, 158, // ..fi(F.mm.Q.
149, 85, 81, 71, 85, 94, 116, 64, 55, 220, 71, 52, // .UQGU^t@7.G4
31, 143, 3, 191, 222, 187, 21, 59, 106, 220, 100, 96, // .......;j.d`
52, 177, 153, 11, 94, 42, 100, 218, 173, 126, 77, 114, // 4...^*d..~Mr
225, 196, 165, 229, 68, 215, 31, 27, 73, 171, 214, 73, // ....D...I..I
57, 225, 237, 40, 236, 150, 42, 88, 74, 165, 239, 42, // 9..(..*XJ..*
213, 131, 189, 49, 176, 96, 180, 89, 80, 38, 90, 196, // ...1.`.YP&Z.
65, 48, 67, 47, 62, 146, 126, 240, 247, 122, 146, 100, // A0C/>.~..z.d
177, 190, 251, 145, 228, 114, 124, 42, 120, 11, 211, 86, // .....r|*x..V
158, 167, 217, 107, 205, 64, 70, 14, 166, 217, 120, 44, // ...k.@F...x,
44, 218, 129, 242, 2, 197, 157, 243, 108, 33, 28, 207, // ,.......l!..
9, 165, 118, 211, 113, 197, 82, 225, 136, 160, 232, 9, // ..v.q.R.....
21, 104, 61, 102, 218, 110, 3, 187, 86, 73, 100, 48, // .h=f.n..VId0
237, 230, 211, 60, 95, 59, 23, 85, 34, 163, 124, 84, // ...<_;.U".|T
52, 189, 209, 100, 25, 150, 90, 49, 151, 50, 117, 242, // 4..d..Z1.2u.
255, 220, 192, 253, 35, 132, 102, 47, 203, 66, 135, 215, // ....#.f/.B..
123, 187, 61, 90, 229, 190, 91, 244, 134, 22, 237, 13, // {.=Z..[.....
104, 76, 12, 49, 230, 175, 26, 156, 0, 115, 53, 217, // hL.1.....s5.
214, 37, 49, 120, 52, 26, 92, 161, 185, 24, 143, 155, // .%1x4.......
166, 24, 40, 150, 242, 101, 14, 4, 250, 189, 6, 23, // ..(..e......
138, 36, 187, 2, 140, 231, 21, 71, 123, 154, 38, 23, // .$.....G{.&.
222, 85, 79, 226, 175, 188, 206, 244, 232, 41, 99, 86, // .UO......)cV
149, 219, 169, 208, 40, 151, 121, 81, 121, 14, 222, 72, // ....(.yQy..H
69, 79, 20, 110, 240, 111, 249, 60, 115, 165, 189, 144, // EO.n.o.<s...
21, 217, 72, 141, 97, 27, 221, 27, 214, 242, 194, 233, // ..H.a.......
215, 212, 109, 178, 80, 94, 174, 60, 152, 50, 65, 72, // ..m.P^.<.2AH
232, 71, 75, 175, 86, 132, 242, 29, 237, 36, 32, 124, // .GK.V....$ |
94, 165, 74, 15, 6, 56, 23, 12, 165, 114, 250, 29, // ^.J..8...r..
159, 202, 119, 94, 13, 116, 149, 36, 232, 76, 26, 53, // ..w^.t.$.L.5
2, 81, 234, 73, 126, 155, 233, 226, 195, 207, 223, 158, // .Q.I~.......
167, 154, 108, 141, 52, 156, 161, 97, 235, 217, 188, 88, // ..l.4..a...X
88, 93, 148, 70, 184, 11, 8, 80, 46, 160, 208, 220, // X].F...P....
47, 228, 27, 47, 192, 76, 92, 211, 3, 85, 140, 70, // /../.L...U.F
59, 116, 11, 177, 239, 209, 237, 218, 59, 60, 30, 34, // ;t......;<."
89, 202, 149, 217, 100, 40, 99, 185, 147, 27, 121, 37, // Y...d(c...y%
175, 229, 157, 188, 80, 21, 113, 15, 34, 210, 52, 137, // ....P.q.".4.
60, 87, 23, 142, 184, 68, 117, 214, 30, 218, 95, 8, // <W...Du..._.
49, 11, 95, 103, 174, 47, 60, 16, 177, 13, 75, 206, // 1._g./<...K.
245, 60, 92, 40, 179, 94, 180, 100, 168, 129, 155, 195, // .<.(.^.d....
101, 158, 167, 58, 236, 105, 196, 102, 70, 48, 254, 16, // e..:.i.fF0..
182, 5, 12, 239, 181, 3, 56, 171, 55, 75, 93, 28, // ......8.7K].
182, 45, 147, 171, 36, 171, 250, 227, 183, 60, 47, 54, // .-..$....</6
96, 20, 128, 203, 194, 255, 170, 40, 194, 221, 36, 41, // `......(..$)
249, 235, 109, 4, 192, 214, 242, 222, 25, 25, 127, 179, // ..m.........
239, 129, 179, 85, 245, 55, 36, 16, 95, 158, 0, 112, // ...U.7$._..p
195, 90, 42, 55, 198, 234, 224, 11, 35, 106, 17, 51, // .Z*7....#j.3
207, 253, 141, 96, 83, 67, 53, 21, 112, 227, 146, 247, // ...`SC5.p...
188, 4, 139, 205, 150, 149, 183, 83, 23, 102, 207, 187, // .......S.f..
209, 136, 49, 40, 181, 163, 15, 213, 8, 189, 162, 58, // ..1(.......:
21, 4, 193, 41, 35, 11, 83, 157, 150, 250, 25, 145, // ...)#.S.....
58, 6, 133, 227, 215, 231, 211, 24, 164, 165, 185, 24, // :...........
95, 76, 74, 251, 215, 200, 238, 9, 202, 97, 51, 186, // _LJ......a3.
187, 99, 54, 236, 223, 65, 4, 54, 114, 167, 118, 77, // .c6..A.6r.vM
147, 30, 72, 129, 188, 82, 27, 35, 198, 49, 10, 56, // ..H..R.#.1.8
42, 48, 201, 142, 190, 3, 69, 2, 127, 215, 52, 222, // *0....E...4.
29, 152, 46, 36, 55, 142, 70, 119, 70, 183, 185, 230, // ...$7.FwF...
232, 45, 109, 99, 204, 212, 136, 154, 230, 10, 141, 194, // .-mc........
138, 241, 213, 204, 90, 229, 107, 160, 187, 86, 87, 71, // ....Z.k..VWG
207, 80, 179, 17, 103, 147, 8, 203, 53, 237, 142, 4, // .P..g...5...
142, 54, 135, 239, 108, 195, 246, 165, 84, 75, 111, 131, // .6..l...TKo.
133, 195, 132, 150, 234, 204, 108, 74, 94, 64, 124, 75, // ......lJ^@|K
33, 87, 144, 144, 124, 203, 136, 161, 86, 129, 177, 182, // !W..|...V...
71, 38, 11, 236, 100, 44, 209, 64, 41, 124, 61, 185, // G&..d,.@)|=.
9, 211, 90, 171, 225, 16, 104, 105, 255, 100, 12, 21, // ..Z...hi.d..
74, 101, 207, 101, 129, 1, 198, 152, 82, 221, 120, 59, // Je.e....R.x;
168, 151, 211, 8, 173, 174, 161, 16, 231, 211, 240, 249, // ............
243, 169, 48, 203, 39, 150, 2, 242, 47, 102, 238, 224, // ..0.'.../f..
8, 195, 104, 228, 74, 138, 5, 41, 110, 151, 118, 227, // ..h.J..)n.v.
85, 50, 196, 41, 37, 228, 79, 30, 193, 72, 150, 42, // U2.)%.O..H.*
65, 71, 196, 29, 251, 23, 70, 21, 239, 250, 170, 248, // AG....F.....
209, 187, 35, 200, 187, 249, 120, 220, 126, 122, 182, 96, // ..#...x.~z.`
105, 108, 129, 209, 126, 24, 4, 86, 237, 10, 104, 170, // il..~..V..h.
195, 131, 163, 2, 42, 216, 58, 115, 94, 84, 36, 122, // ....*.:s^T$z
30, 153, 24, 156, 194, 153, 58, 178, 179, 220, 80, 123, // ......:...P{
233, 229, 140, 221, 63, 35, 171, 132, 63, 60, 222, 24, // ....?#..?<..
39, 24, 227, 214, 169, 233, 29, 222, 103, 125, 227, 100, // '.......g}.d
150, 5, 111, 79, 38, 180, 201, 214, 70, 146, 201, 140, // ..oO&...F...
133, 49, 180, 49, 27, 208, 248, 64, 105, 218, 163, 63, // .1.1...@i..?
192, 161, 1, 43, 216, 52, 166, 154, 247, 248, 39, 180, // ...+.4....'.
223, 130, 1, 160, 56, 96, 45, 44, 186, 158, 132, 219, // ....8`-,....
45, 14, 31, 227, 142, 194, 164, 214, 172, 58, 60, 1, // -........:<.
31, 59, 169, 42, 224, 84, 159, 76, 81, 72, 39, 25, // .;.*.T.LQH'.
124, 144, 15, 201, 50, 53, 71, 88, 242, 186, 61, 135, // |...25GX..=.
146, 177, 122, 73, 246, 144, 102, 23, 172, 131, 56, 171, // ..zI..f...8.
52, 188, 142, 82, 23, 213, 215, 26, 136, 180, 71, 59, // 4..R......G;
5, 250, 194, 157, 172, 221, 89, 48, 171, 253, 188, 143, // ......Y0....
187, 163, 211, 157, 99, 220, 240, 57, 200, 14, 155, 122, // ....c..9...z
178, 128, 147, 90, 106, 246, 24, 129, 122, 231, 49, 225, // ...Zj...z.1.
53, 14, 119, 107, 121, 131, 217, 112, 232, 59, 59, 58, // 5.wky..p.;;:
104, 101, 176, 105, 162, 73, 165, 203, 202, 203, 196, 44, // he.i.I.....,
240, 131, 241, 112, 123, 55, 236, 166, 185, 232, 216, 97, // ...p{7.....a
152, 81, 76, 153, 110, 176, 209, 187, 84, 243, 204, 194, // .QL.n...T...
84, 15, 77, 118, 0, 250, 49, 200, 36, 42, 203, 143, // T.Mv..1.$*..
228, 160, 5, 134, 114, 199, 128, 43, 246, 23, 14, 193, // ....r..+....
43, 210, 62, 248, 252, 68, 233, 140, 220, 230, 74, 4, // +.>..D....J.
208, 20, 246, 246, 155, 230, 206, 193, 99, 113, 128, 35, // ........cq.#
225, 8, 58, 208, 64, 0, 99, 64, 59, 199, 20, 248, // ..:.@.c@;...
28, 194, 83, 135, 216, 59, 57, 25, 230, 142, 124, 163, // ..S..;9...|.
209, 48, 51, 229, 211, 133, 128, 11, 2, 250, 227, 104, // .03........h
167, 168, 100, 155, 134, 145, 246, 94, 156, 133, 91, 176, // ..d....^..[.
71, 127, 242, 130, 166, 132, 61, 67, 95, 149, 191, 205, // G.....=C_...
111, 117, 113, 6, 23, 201, 19, 152, 89, 207, 30, 180, // ouq.....Y...
77, 202, 52, 193, 88, 68, 11, 89, 91, 132, 22, 164, // M.4.XD.Y[...
176, 163, 248, 69, 16, 195, 181, 121, 54, 46, 16, 158, // ...E...y6...
200, 96, 86, 53, 13, 4, 47, 142, 207, 111, 32, 139, // .`V5../..o .
111, 147, 178, 210, 240, 5, 192, 202, 98, 246, 193, 63, // o.......b..?
135, 152, 192, 54, 153, 40, 233, 41, 128, 86, 1, 134, // ...6.(.).V..
113, 152, 93, 233, 34, 175, 203, 116, 247, 65, 87, 223, // q.]."..t.AW.
101, 128, 187, 248, 248, 195, 91, 50, 134, 198, 59, 206, // e.....[2..;.
197, 193, 246, 238, 32, 96, 215, 243, 11, 127, 189, 192, // .... `......
6, 215, 67, 209, 245, 148, 151, 225, 134, 183, 93, 14, // ..C.......].
123, 248, 215, 20, 98, 17, 50, 16, 46, 197, 66, 92, // {...b.2...B.
25, 108, 216, 184, 114, 21, 46, 191, 35, 255, 218, 213, // .l..r...#...
99, 248, 54, 105, 30, 198, 182, 206, 220, 210, 162, 42, // c.6i.......*
118, 247, 15, 5, 53, 152, 90, 101, 217, 71, 97, 21, // v...5.Ze.Ga.
113, 120, 176, 63, 102, 66, 65, 72, 235, 185, 66, 136, // qx.?fBAH..B.
6, 167, 3, 214, 249, 97, 216, 99, 106, 209, 50, 213, // .....a.cj.2.
40, 200, 87, 21, 196, 111, 89, 87, 218, 106, 136, 37, // (.W..oYW.j.%
104, 175, 89, 244, 253, 218, 115, 154, 154, 67, 141, 116, // h.Y...s..C.t
110, 92, 246, 241, 224, 116, 225, 101, 19, 77, 28, 152, // n....t.e.M..
217, 47, 57, 241, 253, 144, 245, 195, 145, 81, 39, 255, // ./9......Q'.
118, 20, 29, 203, 189, 176, 93, 38, 50, 50, 90, 183, // v.....]&22Z.
146, 161, 220, 202, 27, 235, 155, 45, 229, 25, 121, 103, // .......-..yg
240, 200, 204, 9, 114, 96, 27, 131, 73, 47, 58, 19, // ....r`..I/:.
189, 24, 108, 106, 232, 68, 254, 220, 26, 180, 138, 76, // ..lj.D.....L
9, 38, 204, 156, 91, 21, 27, 101, 42, 175, 77, 248, // .&..[..e*.M.
80, 171, 121, 130, 131, 222, 91, 177, 153, 93, 194, 172, // P.y...[..]..
145, 146, 77, 153, 89, 108, 2, 30, 115, 227, 156, 229, // ..M.Yl..s...
138, 252, 31, 227, 45, 157, 41, 140, 62, 119, 49, 218, // ....-.).>w1.
71, 242, 73, 70, 163, 124, 190, 34, 183, 0, 135, 145, // G.IF.|."....
90, 205, 206, 102, 103, 6, 214, 28, 185, 62, 117, 33, // Z..fg....>u!
70, 165, 197, 68, 179, 43, 133, 19, 141, 86, 100, 214, // F..D.+...Vd.
26, 145, 255, 172, 66, 252, 156, 251, 222, 16, 163, 170, // ....B.......
156, 230, 29, 66, 134, 206, 71, 163, 243, 73, 219, 2, // ...B..G..I..
142, 82, 208, 48, 51, 67, 67, 149, 233, 91, 176, 113, // .R.03CC..[.q
41, 239, 132, 239, 245, 219, 98, 110, 147, 97, 159, 98, // ).....bn.a.b
234, 28, 117, 51, 94, 125, 37, 228, 217, 104, 116, 54, // ..u3^}%..ht6
41, 235, 165, 23, 18, 156, 137, 60, 151, 40, 149, 85, // )......<.(.U
88, 105, 200, 158, 45, 177, 34, 135, 109, 48, 122, 39, // Xi..-.".m0z'
105, 149, 153, 202, 229, 150, 215, 75, 129, 16, 55, 173, // i......K..7.
217, 119, 50, 98, 78, 117, 248, 20, 30, 127, 149, 69, // .w2bNu.....E
228, 220, 164, 243, 201, 149, 174, 222, 32, 240, 185, 209, // ........ ...
241, 7, 234, 248, 166, 200, 55, 156, 12, 104, 71, 184, // ......7..hG.
33, 109, 3, 71, 25, 92, 132, 117, 42, 77, 163, 124, // !m.G...u*M.|
26, 145, 183, 116, 192, 66, 222, 40, 187, 57, 248, 132, // ...t.B.(.9..
22, 173, 220, 10, 179, 206, 191, 90, 138, 89, 44, 109, // .......Z.Y,m
124, 179, 205, 51, 72, 244, 47, 73, 154, 254, 128, 192, // |..3H./I....
13, 6, 248, 88, 171, 231, 246, 215, 235, 124, 147, 196, // ...X.....|..
237, 8, 80, 200, 248, 142, 71, 250, 69, 123, 128, 252, // ..P...G.E{..
251, 117, 45, 161, 8, 55, 79, 44, 239, 189, 142, 52, // .u-..7O,...4
198, 88, 200, 191, 232, 52, 210, 49, 8, 141, 83, 230, // .X...4.1..S.
112, 149, 235, 188, 78, 227, 51, 55, 232, 167, 109, 204, // p...N.37..m.
60, 24, 156, 42, 245, 84, 175, 163, 52, 208, 53, 77, // <..*.T..4.5M
192, 65, 160, 98, 137, 190, 17, 247, 143, 132, 202, 200, // .A.b........
5, 43, 226, 205, 192, 130, 89, 22, 67, 140, 78, 5, // .+....Y.C.N.
163, 186, 161, 195, 226, 129, 218, 94, 115, 249, 218, 148, // .......^s...
39, 176, 194, 231, 33, 236, 102, 63, 140, 213, 54, 46, // '...!.f?..6.
87, 129, 216, 27, 60, 107, 235, 166, 140, 70, 169, 165, // W...<k...F..
187, 104, 237, 238, 81, 226, 185, 237, 30, 109, 238, 237, // .h..Q....m..
243, 40, 155, 187, 193, 45, 159, 219, 229, 17, 37, 30, // .(...-....%.
195, 122, 108, 242, 40, 122, 61, 84, 174, 227, 52, 179, // .zl.(z=T..4.
166, 170, 176, 166, 74, 58, 154, 181, 36, 163, 239, 59, // ....J:..$..;
248, 172, 43, 229, 116, 220, 115, 114, 239, 164, 190, 157, // ..+.t.sr....
71, 60, 64, 238, 54, 4, 161, 99, 151, 240, 204, 128, // G<@.6..c....
145, 35, 12, 205, 179, 17, 190, 124, 212, 239, 145, 122, // .#.....|...z
109, 157, 3, 202, 221, 31, 178, 112, 11, 57, 177, 222, // m......p.9..
159, 217, 40, 76, 201, 230, 233, 94, 34, 3, 208, 92, // ..(L...^"...
40, 179, 8, 196, 93, 43, 23, 234, 173, 141, 100, 42, // (...]+....d*
181, 162, 24, 112, 182, 178, 214, 180, 13, 110, 87, 146, // ...p.....nW.
194, 253, 195, 8, 248, 66, 204, 46, 252, 249, 197, 226, // .....B......
209, 89, 131, 229, 119, 217, 158, 254, 89, 240, 132, 172, // .Y..w...Y...
200, 43, 43, 153, 231, 76, 36, 134, 53, 100, 215, 32, // .++..L$.5d.
187, 241, 177, 108, 82, 16, 14, 89, 95, 240, 103, 222, // ...lR..Y_.g.
67, 145, 181, 162, 44, 124, 83, 185, 245, 172, 100, 247, // C...,|S...d.
150, 24, 137, 41, 179, 56, 78, 86, 43, 29, 91, 46, // ...).8NV+.[.
119, 254, 129, 153, 128, 215, 235, 69, 134, 226, 3, 85, // w......E...U
11, 27, 62, 105, 149, 216, 29, 13, 6, 145, 172, 231, // ..>i........
117, 155, 249, 75, 196, 194, 174, 156, 164, 71, 155, 51, // u..K.....G.3
184, 239, 2, 188, 161, 38, 113, 79, 189, 17, 37, 48, // .....&qO..%0
241, 65, 60, 163, 197, 163, 84, 17, 128, 248, 120, 100, // .A<...T...xd
2, 174, 237, 116, 199, 83, 74, 54, 161, 76, 154, 216, // ...t.SJ6.L..
237, 160, 157, 159, 109, 195, 190, 159, 180, 185, 245, 250, // ....m.......
41, 155, 214, 49, 40, 217, 49, 88, 131, 118, 70, 140, // )..1(.1X.vF.
227, 246, 236, 221, 89, 231, 64, 110, 16, 163, 176, 215, // ....Y.@n....
125, 67, 46, 183, 218, 113, 222, 106, 112, 226, 84, 180, // }C...q.jp.T.
102, 191, 121, 186, 121, 93, 187, 144, 101, 99, 50, 56, // f.y.y]..ec28
136, 109, 235, 249, 134, 67, 189, 146, 60, 40, 136, 232, // .m...C..<(..
110, 6, 127, 38, 199, 194, 201, 33, 4, 42, 255, 21, // n..&...!.*..
194, 226, 9, 165, 115, 249, 108, 23, 216, 129, 42, 37, // ....s.l...*%
141, 50, 177, 146, 201, 57, 244, 18, 177, 157, 245, 86, // .2...9.....V
59, 231, 155, 196, 121, 196, 57, 245, 73, 4, 232, 74, // ;...y.9.I..J
147, 247, 79, 65, 152, 23, 139, 105, 166, 138, 217, 131, // ..OA...i....
110, 155, 20, 187, 252, 0, 7, 180, 170, 182, 254, 139, // n...........
23, 183, 183, 183, 147, 219, 87, 147, 188, 184, 122, 241, // ......W...z.
242, 228, 228, 228, 5, 237, 19, 234, 226, 31, 31, 232, // ............
237, 100, 12, 69, 24, 141, 98, 23, 209, 201, 136, 100, // .d.E..b....d
181, 191, 176, 53, 126, 99, 196, 69, 196, 107, 168, 95, // ...5~c.E.k._
104, 170, 158, 173, 196, 221, 65, 84, 147, 92, 91, 78, // h.....AT..[N
102, 70, 231, 104, 233, 37, 116, 64, 121, 45, 83, 154, // fF.h.%t@y-S.
38, 21, 147, 39, 188, 113, 56, 8, 241, 147, 125, 131, // &..'.q8...}.
168, 37, 152, 227, 211, 154, 174, 114, 136, 163, 155, 215, // .%.....r....
217, 36, 116, 46, 107, 217, 103, 221, 122, 222, 239, 1, // .$t.k.g.z...
47, 38, 25, 184, 69, 119, 10, 135, 173, 236, 112, 77, // /&..Ew....pM
61, 216, 166, 144, 120, 188, 37, 85, 30, 141, 182, 36, // =...x.%U...$
179, 213, 198, 250, 39, 84, 106, 154, 174, 13, 72, 18, // ....'Tj...H.
183, 60, 193, 36, 105, 171, 106, 219, 13, 134, 7, 142, // .<.$i.j.....
8, 137, 104, 218, 79, 190, 30, 134, 145, 180, 155, 194, // ..h.O.......
94, 222, 56, 107, 69, 242, 137, 88, 220, 94, 230, 112, // ^.8kE..X.^.p
88, 206, 55, 38, 77, 67, 113, 168, 185, 242, 64, 252, // X.7&MCq...@.
86, 44, 160, 159, 29, 130, 76, 228, 20, 118, 56, 111, // V,....L..v8o
180, 13, 109, 51, 0, 2, 217, 211, 200, 135, 76, 2, // ..m3......L.
87, 137, 214, 58, 186, 214, 177, 173, 210, 44, 28, 55, // W..:.....,.7
16, 14, 59, 59, 77, 108, 103, 223, 67, 29, 99, 185, // ..;;Mlg.C.c.
70, 43, 172, 230, 86, 184, 100, 104, 27, 29, 109, 156, // F+..V.dh..m.
30, 182, 150, 24, 118, 56, 147, 143, 50, 145, 27, 31, // ....v8..2...
172, 112, 138, 109, 130, 39, 157, 92, 101, 63, 46, 127, // .p.m.'..e?..
215, 17, 71, 84, 59, 214, 246, 122, 86, 35, 152, 241, // ..GT;..zV#..
43, 147, 9, 163, 60, 16, 244, 55, 58, 84, 225, 141, // +...<..7:T..
234, 52, 184, 203, 62, 145, 50, 146, 161, 100, 85, 158, // .4..>.2..dU.
194, 44, 122, 118, 215, 32, 92, 12, 84, 46, 108, 192, // .,zv. ..T.l.
240, 216, 136, 4, 9, 195, 134, 147, 44, 92, 5, 101, // ........,..e
176, 145, 171, 66, 151, 165, 53, 31, 131, 13, 64, 46, // ...B..5...@.
176, 27, 139, 9, 49, 201, 218, 192, 74, 242, 79, 90, // ....1...J.OZ
66, 30, 155, 193, 246, 81, 234, 146, 167, 176, 117, 139, // B....Q....u.
207, 141, 100, 140, 182, 66, 56, 197, 254, 113, 162, 232, // ..d..B8..q..
163, 181, 211, 108, 113, 143, 93, 175, 204, 180, 199, 225, // ...lq.].....
93, 84, 23, 148, 216, 81, 193, 99, 59, 123, 96, 229, // ]T...Q.c;{`.
127, 114, 8, 237, 45, 35, 223, 188, 76, 234, 108, 99, // .r..-#..L.lc
156, 211, 182, 8, 4, 146, 83, 97, 38, 59, 234, 229, // ......Sa&;..
110, 6, 132, 54, 174, 72, 25, 36, 154, 163, 105, 62, // n..6.H.$..i>
82, 10, 140, 197, 182, 77, 129, 218, 60, 90, 100, 18, // R....M..<Zd.
199, 249, 3, 79, 202, 76, 194, 49, 241, 241, 46, 239, // ...O.L.1....
216, 129, 33, 246, 185, 57, 186, 115, 118, 113, 56, 201, // ..!..9.svq8.
75, 200, 77, 198, 142, 229, 163, 128, 213, 40, 94, 231, // K.M......(^.
78, 70, 10, 152, 138, 28, 194, 60, 26, 253, 228, 229, // NF.....<....
44, 217, 242, 136, 14, 153, 216, 21, 81, 159, 243, 96, // ,.......Q..`
236, 182, 86, 230, 206, 73, 200, 238, 166, 200, 165, 224, // ..V..I......
58, 138, 126, 229, 114, 84, 150, 123, 238, 194, 206, 197, // :.~.rT.{....
90, 102, 225, 45, 248, 15, 94, 223, 64, 144, 220, 79, // Zf.-..^.@..O
105, 127, 230, 196, 165, 62, 178, 216, 216, 198, 177, 124, // i....>.....|
163, 48, 87, 7, 57, 241, 128, 239, 43, 140, 99, 193, // .0W.9...+.c.
151, 222, 239, 160, 46, 129, 242, 6, 208, 175, 28, 29, // ............
130, 117, 53, 244, 214, 134, 47, 243, 0, 17, 89, 77, // .u5.../...YM
121, 240, 180, 187, 132, 169, 30, 93, 194, 240, 232, 217, // y......]....
60, 95, 248, 181, 153, 170, 154, 172, 146, 162, 52, 190, // <_........4.
158, 187, 30, 174, 250, 103, 128, 185, 167, 73, 236, 200, // .....g...I..
28, 227, 106, 162, 213, 193, 64, 74, 252, 189, 241, 146, // ..j...@J....
3, 50, 124, 99, 46, 170, 248, 2, 82, 221, 243, 229, // .2|c....R...
171, 26, 226, 115, 54, 28, 215, 227, 49, 221, 215, 106, // ...s6...1..j
9, 231, 178, 196, 225, 86, 248, 79, 92, 110, 57, 163, // .....V.O.n9.
227, 101, 98, 47, 17, 204, 220, 36, 241, 1, 176, 69, // .eb/...$...E
47, 171, 105, 159, 53, 15, 92, 87, 216, 10, 119, 129, // /.i.5..W..w.
133, 240, 150, 242, 51, 4, 37, 143, 129, 170, 158, 31, // ....3.%.....
239, 48, 238, 13, 228, 209, 136, 72, 245, 151, 210, 93, // .0.....H...]
234, 26, 43, 194, 202, 195, 37, 114, 26, 217, 115, 66, // ..+...%r..sB
8, 96, 177, 213, 203, 131, 177, 129, 187, 91, 156, 186, // .`.......[..
71, 5, 199, 84, 102, 122, 188, 185, 191, 106, 76, 180, // G..Tfz...jL.
229, 252, 92, 208, 187, 17, 150, 48, 103, 252, 50, 129, // .......0g.2.
185, 75, 215, 157, 36, 240, 237, 237, 116, 123, 197, 29, // .K..$...t{..
76, 28, 141, 57, 186, 154, 56, 246, 244, 51, 31, 176, // L..9..8..3..
63, 112, 65, 77, 18, 80, 102, 196, 88, 253, 128, 123, // ?pAM.Pf.X..{
237, 181, 51, 105, 193, 52, 227, 88, 102, 202, 158, 88, // ..3i.4.Xf..X
192, 229, 136, 46, 80, 233, 164, 97, 227, 64, 237, 213, // ....P..a.@..
131, 108, 143, 139, 82, 171, 99, 161, 241, 121, 81, 228, // .l..R.c..yQ.
5, 59, 195, 37, 162, 12, 106, 245, 158, 134, 195, 102, // .;.%..j....f
133, 204, 205, 253, 131, 179, 91, 193, 65, 128, 118, 70, // ......[.A.vF
54, 136, 209, 61, 106, 37, 202, 181, 99, 243, 254, 117, // 6..=j%..c..u
248, 121, 107, 133, 177, 95, 173, 178, 125, 181, 46, 242, // .yk.._..}...
91, 4, 155, 123, 104, 232, 9, 60, 179, 46, 135, 227, // [..{h..<....
22, 169, 14, 137, 100, 238, 229, 3, 27, 9, 177, 76, // ....d......L
112, 26, 197, 149, 72, 121, 89, 80, 104, 236, 204, 181, // p...HyYPh...
250, 174, 96, 146, 36, 29, 196, 209, 235, 39, 142, 147, // ..`.$....'..
149, 54, 65, 29, 226, 200, 78, 64, 65, 20, 116, 150, // .6A...N@A.t.
198, 251, 183, 215, 240, 237, 220, 20, 166, 103, 109, 205, // .........gm.
6, 184, 153, 144, 27, 143, 154, 112, 136, 29, 236, 15, // .......p....
220, 142, 244, 83, 218, 96, 144, 217, 162, 166, 236, 145, // ...S.`......
126, 136, 88, 63, 133, 216, 38, 175, 214, 230, 54, 59, // ~.X?..&...6;
63, 102, 46, 33, 173, 155, 164, 212, 51, 251, 237, 13, // ?f.!....3...
174, 214, 58, 155, 44, 161, 1, 158, 235, 195, 193, 159, // ..:.,.......
167, 55, 26, 113, 172, 15, 150, 124, 76, 54, 58, 175, // .7.q...|L6:.
43, 105, 110, 219, 79, 96, 144, 79, 88, 243, 222, 202, // +in.O`.OX...
75, 249, 139, 124, 143, 150, 239, 104, 214, 31, 77, 206, // K..|...h..M.
80, 254, 108, 2, 114, 249, 71, 27, 181, 201, 175, 141, // P.l.r.G.....
44, 203, 79, 84, 123, 162, 118, 15, 138, 126, 239, 34, // ,.OT{.v..~."
173, 181, 177, 251, 107, 239, 82, 106, 249, 30, 14, 153, // ....k.Rj....
32, 244, 60, 89, 165, 46, 209, 115, 1, 251, 196, 95, // .<Y...s..._
210, 37, 31, 147, 210, 243, 148, 249, 98, 223, 222, 42, // .%......b..*
233, 47, 57, 164, 108, 195, 86, 174, 48, 237, 40, 91, // ./9.l.V.0.([
71, 181, 185, 94, 116, 118, 247, 219, 222, 19, 148, 247, // G..^tv......
234, 84, 254, 233, 37, 90, 246, 179, 179, 127, 30, 220, // .T..%Z......
149, 169, 223, 189, 183, 48, 199, 47, 219, 233, 170, 73, // .....0./...I
69, 143, 82, 38, 124, 229, 201, 209, 171, 154, 7, 179, // E.R&|.......
0, 18, 224, 39, 218, 230, 103, 33, 193, 242, 209, 195, // ...'..g!....
2, 172, 178, 98, 120, 184, 120, 146, 206, 90, 83, 52, // ...bx.x..ZS4
41, 114, 139, 40, 51, 235, 61, 93, 44, 204, 12, 157, // )r.(3.=],...
14, 99, 47, 98, 111, 91, 213, 165, 217, 87, 183, 230, // .c/bo[...W..
191, 25, 130, 246, 87, 252, 74, 76, 7, 153, 81, 154, // ....W.JL..Q.
84, 51, 250, 11, 73, 175, 74, 204, 76, 102, 7, 23, // T3..I.J.Lf..
42, 144, 76, 219, 78, 222, 42, 209, 35, 197, 247, 143, // *.L.N.*.#...
209, 126, 246, 127, 64, 123, 12, 229, 223, 15, 200, 255, // .~..@{......
185, 252, 213, 123, 116, 166, 220, 91, 239, 202, 39, 123, // ...{t..[..'{
49, 239, 95, 99, 254, 195, 177, 230, 189, 250, 66, 126, // 1._c......B~
223, 31, 249, 132, 103, 152, 145, 60, 155, 124, 152, 243, // ....g..<.|..
15, 169, 105, 47, 221, 21, 68, 224, 179, 105, 133, 177, // ..i/..D..i..
34, 83, 216, 205, 244, 107, 255, 116, 54, 59, 255, 175, // "S...k.t6;..
86, 4, 82, 205, 169, 134, 11, 64, 216, 172, 3, 172, // V.R....@....
136, 224, 112, 254, 66, 101, 54, 31, 160, 77, 67, 135, // ..p.Be6..MC.
242, 159, 7, 135, 247, 123, 245, 223, 199, 246, 14, 27, // .....{......
9, 160, 110, 144, 214, 157, 252, 92, 186, 115, 102, 206, // ..n......sf.
126, 37, 52, 193, 174, 236, 127, 68, 119, 66, 69, 116, // ~%4....DwBEt
87, 235, 46, 223, 3, 246, 171, 204, 10, 97, 92, 50, // W........a.2
78, 113, 95, 146, 135, 218, 63, 136, 201, 123, 238, 47, // Nq_...?..{./
52, 211, 78, 61, 235, 82, 191, 209, 203, 250, 234, 103, // 4.N=.R.....g
115, 74, 63, 104, 240, 72, 236, 31, 92, 109, 4, 189, // sJ?h.H...m..
245, 154, 197, 157, 34, 132, 9, 212, 183, 94, 119, 11, // ...."....^w.
108, 4, 229, 242, 241, 129, 194, 154, 254, 168, 245, 192, // l...........
108, 246, 60, 69, 34, 48, 52, 133, 206, 107, 1, 247, // l.<E"04..k..
142, 180, 170, 127, 208, 83, 151, 209, 70, 232, 77, 183, // .....S..F.M.
64, 168, 146, 184, 255, 238, 104, 222, 52, 49, 222, 238, // @.....h.41..
59, 115, 81, 213, 170, 133, 3, 45, 172, 27, 124, 216, // ;sQ....-..|.
90, 247, 91, 97, 19, 237, 185, 23, 136, 251, 126, 171, // Z.[a......~.
77, 57, 153, 247, 104, 156, 242, 97, 3, 186, 103, 243, // M9..h..a..g.
121, 176, 193, 75, 147, 172, 248, 113, 52, 250, 145, 118, // y..K...q4..v
198, 3, 139, 3, 136, 159, 71, 163, 159, 105, 243, 111, // ......G..i.o
173, 153, 204, 148, 119, 105, 35, 13, 154, 145, 222, 88, // ....wi#....X
122, 217, 163, 149, 103, 143, 86, 157, 217, 181, 241, 36, // z...g.V....$
198, 106, 31, 204, 243, 199, 104, 244, 135, 243, 184, 204, // .j....h.....
19, 178, 104, 26, 152, 252, 222, 133, 253, 28, 164, 11, // ..h.........
61, 186, 149, 251, 206, 168, 60, 89, 132, 95, 56, 143, // =.....<Y._8.
80, 232, 63, 106, 93, 86, 95, 101, 201, 38, 36, 204, // P.?j]V_e.&$.
223, 20, 225, 134, 210, 160, 222, 47, 79, 117, 10, 132, // ......./Ou..
29, 143, 31, 101, 245, 157, 184, 40, 213, 97, 97, 143, // ...e...(.aa.
40, 88, 23, 153, 67, 54, 163, 48, 139, 116, 122, 136, // (X..C6.0.tz.
137, 78, 229, 238, 48, 99, 114, 86, 170, 215, 16, 64, // .N..0crV...@
56, 79, 196, 148, 134, 123, 153, 58, 186, 24, 236, 4, // 8O...{.:....
226, 229, 85, 228, 39, 93, 186, 200, 135, 73, 23, 245, // ..U.']...I..
61, 150, 128, 61, 203, 135, 201, 63, 39, 71, 143, 101, // =..=...?'G.e
104, 173, 108, 123, 146, 86, 186, 56, 24, 100, 180, 132, // h.l{.V.8.d..
31, 216, 53, 77, 173, 89, 188, 173, 80, 85, 71, 103, // ..5M.Y..PUGg
209, 230, 20, 245, 116, 203, 79, 82, 184, 86, 230, 170, // ....t.OR.V..
158, 204, 125, 61, 26, 125, 109, 162, 49, 217, 158, 202, // ..}=.}m.1...
7, 60, 255, 100, 52, 250, 228, 33, 207, 233, 210, 221, // .<.d4..!....
242, 155, 53, 195, 113, 190, 191, 169, 167, 115, 155, 140, // ..5.q....s..
42, 215, 199, 220, 147, 163, 4, 239, 156, 132, 162, 111, // *..........o
250, 166, 71, 95, 86, 114, 162, 150, 63, 30, 177, 167, // ..G_Vr..?...
151, 54, 168, 15, 6, 51, 8, 111, 231, 33, 92, 170, // .6...3.o.!..
251, 86, 121, 160, 233, 94, 222, 8, 52, 231, 45, 76, // .Vy..^..4.-L
17, 65, 241, 3, 178, 247, 195, 93, 122, 65, 64, 111, // .A.....]zA@o
161, 251, 105, 220, 228, 0, 237, 177, 231, 195, 179, 140, // ..i.........
31, 132, 238, 105, 137, 209, 161, 247, 219, 75, 79, 76, // ...i.....KOL
233, 114, 27, 122, 238, 98, 134, 66, 157, 34, 184, 207, // .r.z.b.B."..
250, 193, 189, 121, 59, 67, 25, 172, 241, 120, 33, 83, // ...y;C...x!S
78, 101, 193, 254, 99, 92, 163, 234, 217, 169, 255, 146, // Ne..c.......
94, 66, 112, 231, 2, 243, 205, 199, 227, 98, 49, 125, // ^Bp......b1}
165, 232, 209, 73, 69, 184, 83, 255, 51, 91, 57, 93, // ...IE.S.3[9]
40, 147, 143, 154, 132, 101, 153, 92, 101, 30, 53, 53, // (....e..e.55
13, 124, 227, 84, 248, 159, 51, 16, 55, 41, 215, 142, // .|.T..3.7)..
88, 145, 209, 17, 146, 47, 90, 36, 174, 113, 172, 210, // X..../Z$.q..
241, 112, 136, 112, 152, 179, 19, 225, 118, 155, 238, 188, // .p.p....v...
84, 70, 68, 24, 122, 214, 56, 31, 14, 249, 16, 94, // TFD.z.8....^
8, 242, 101, 216, 104, 228, 66, 166, 244, 190, 197, 172, // ..e.h.B.....
253, 165, 143, 77, 20, 207, 95, 98, 251, 156, 146, 83, // ...M.._b...S
57, 142, 114, 11, 153, 182, 153, 34, 132, 159, 244, 14, // 9.r...."....
86, 223, 62, 251, 33, 220, 202, 213, 161, 143, 109, 216, // V.>.!.....m.
15, 231, 22, 225, 143, 241, 161, 219, 51, 136, 146, 154, // ........3...
237, 176, 146, 195, 16, 134, 160, 231, 74, 18, 93, 88, // ........J.]X
167, 169, 242, 88, 109, 146, 160, 4, 68, 65, 93, 127, // ...Xm...DA].
14, 199, 25, 230, 26, 220, 73, 56, 226, 67, 89, 208, // ......I8.CY.
79, 173, 232, 72, 74, 15, 160, 233, 246, 144, 159, 193, // O..HJ.......
0, 95, 174, 242, 238, 237, 197, 191, 126, 43, 255, 243, // ._......~+..
183, 12, 63, 141, 43, 124, 242, 226, 138, 31, 160, 136, // ..?.+|......
89, 109, 54, 141, 224, 0, 81, 22, 229, 226, 29, 138, // Ym6...Q.....
92, 204, 60, 219, 249, 138, 59, 177, 130, 151, 194, 127, // ..<...;.....
105, 32, 134, 147, 201, 132, 82, 121, 57, 84, 196, 225, // i ....Ry9T..
248, 12, 96, 39, 45, 4, 122, 6, 109, 215, 231, 242, // ..`'-.z.m...
68, 194, 71, 192, 12, 213, 151, 234, 115, 122, 159, 155, // D.G.....sz..
55, 205, 0, 166, 145, 88, 95, 145, 163, 99, 1, 43, // 7....X_..c.+
0, 230, 28, 47, 169, 47, 56, 78, 234, 58, 128, 220, // ..././8N.:..
117, 8, 166, 196, 158, 159, 78, 37, 175, 117, 247, 78, // u.....N%.u.N
138, 222, 54, 210, 97, 97, 150, 144, 66, 33, 83, 47, // ..6.aa..B!S/
17, 162, 21, 241, 8, 3, 162, 215, 122, 158, 44, 220, // ........z.,.
152, 8, 99, 16, 242, 163, 101, 14, 167, 135, 7, 206, // ..c...e.....
134, 175, 249, 185, 199, 204, 35, 4, 160, 116, 13, 215, // ......#..t..
88, 189, 18, 126, 62, 86, 25, 75, 52, 64, 158, 63, // X..~>V.K4@.?
183, 219, 31, 126, 105, 129, 29, 131, 0, 167, 178, 113, // ...~i......q
78, 185, 214, 98, 150, 81, 38, 120, 70, 44, 51, 163, // N..b.Q&xF,3.
63, 29, 126, 106, 238, 65, 134, 159, 154, 97, 5, 26, // ?.~j.A...a..
91, 20, 52, 31, 208, 128, 74, 244, 216, 79, 181, 136, // [.4...J..O..
63, 135, 205, 205, 45, 242, 225, 11, 110, 38, 167, 248, // ?...-...n&..
245, 231, 192, 195, 99, 205, 250, 199, 244, 62, 133, 145, // ....c....>..
56, 62, 214, 138, 114, 190, 132, 180, 150, 174, 98, 232, // 8>..r.....b.
249, 18, 212, 172, 168, 3, 28, 27, 62, 27, 218, 69, // ........>..E
253, 86, 181, 165, 172, 45, 21, 7, 171, 123, 105, 232, // .V...-...{i.
208, 206, 49, 28, 180, 164, 192, 74, 63, 147, 118, 22, // ..1....J?.v.
167, 67, 76, 194, 61, 167, 2, 48, 166, 251, 191, 15, // .CL.=..0....
56, 74, 132, 251, 175, 17, 167, 179, 204, 39, 189, 220, // 8J.......'..
155, 168, 49, 20, 83, 125, 183, 205, 139, 234, 62, 124, // ..1.S}....>|
22, 150, 207, 214, 208, 60, 254, 86, 155, 84, 254, 64, // .....<.V.T.@
37, 19, 157, 202, 152, 202, 109, 82, 72, 126, 67, 85, // %.....mRH~CU
115, 79, 99, 51, 74, 242, 91, 106, 130, 91, 201, 81, // sOc3J.[j.[.Q
142, 252, 211, 214, 222, 235, 184, 142, 48, 254, 111, 182, // ........0.o.
126, 14, 239, 36, 170, 228, 247, 182, 250, 54, 220, 225, // ~..$.....6..
252, 182, 141, 127, 111, 199, 172, 228, 63, 108, 249, 187, // ....o...?l..
205, 86, 23, 56, 84, 110, 244, 69, 152, 197, 169, 150, // .V.8Tn.E....
191, 218, 142, 31, 244, 38, 151, 255, 180, 149, 179, 48, // .....&.....0
77, 151, 97, 116, 45, 181, 118, 45, 118, 85, 153, 107, // M.at-.v-vU.k
232, 188, 93, 25, 184, 54, 206, 156, 124, 141, 179, 51, // ..]..6..|..3
14, 139, 221, 126, 250, 31, 255, 11, 22, 19, 178, 116, // ...~.......t
138, 51, 0, 0, 0 // .3..
60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 104, 116, // <!DOCTYPE ht
109, 108, 62, 10, 60, 104, 116, 109, 108, 32, 108, 97, // ml>.<html la
110, 103, 61, 34, 101, 110, 34, 62, 10, 32, 32, 60, // ng="en">. <
104, 101, 97, 100, 62, 10, 32, 32, 32, 32, 60, 109, // head>. <m
101, 116, 97, 32, 110, 97, 109, 101, 61, 34, 100, 101, // eta name="de
115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 99, // scription" c
111, 110, 116, 101, 110, 116, 61, 34, 77, 111, 110, 103, // ontent="Mong
111, 111, 115, 101, 32, 69, 109, 98, 101, 100, 100, 101, // oose Embedde
100, 32, 70, 105, 108, 101, 115, 121, 116, 101, 109, 32, // d Filesytem
101, 120, 97, 109, 112, 108, 101, 34, 32, 47, 62, 10, // example" />.
32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // <meta ht
116, 112, 45, 101, 113, 117, 105, 118, 61, 34, 67, 111, // tp-equiv="Co
110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 34, 32, // ntent-Type"
99, 111, 110, 116, 101, 110, 116, 61, 34, 116, 101, 120, // content="tex
116, 47, 104, 116, 109, 108, 59, 32, 99, 104, 97, 114, // t/html; char
115, 101, 116, 61, 85, 84, 70, 45, 56, 34, 62, 10, // set=UTF-8">.
32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // <meta ht
116, 112, 45, 101, 113, 117, 105, 118, 61, 34, 88, 45, // tp-equiv="X-
85, 65, 45, 67, 111, 109, 112, 97, 116, 105, 98, 108, // UA-Compatibl
101, 34, 32, 99, 111, 110, 116, 101, 110, 116, 61, 34, // e" content="
73, 69, 61, 101, 100, 103, 101, 34, 62, 10, 32, 32, // IE=edge">.
32, 32, 60, 109, 101, 116, 97, 32, 110, 97, 109, 101, // <meta name
61, 34, 118, 105, 101, 119, 112, 111, 114, 116, 34, 32, // ="viewport"
99, 111, 110, 116, 101, 110, 116, 61, 34, 119, 105, 100, // content="wid
116, 104, 61, 100, 101, 118, 105, 99, 101, 45, 119, 105, // th=device-wi
100, 116, 104, 44, 32, 105, 110, 105, 116, 105, 97, 108, // dth, initial
45, 115, 99, 97, 108, 101, 61, 49, 34, 62, 10, 32, // -scale=1">.
32, 32, 32, 32, 32, 32, 32, 60, 116, 105, 116, 108, // <titl
101, 62, 77, 111, 110, 103, 111, 111, 115, 101, 32, 69, // e>Mongoose E
109, 98, 101, 100, 100, 101, 100, 32, 70, 105, 108, 101, // mbedded File
115, 121, 116, 101, 109, 32, 101, 120, 97, 109, 112, 108, // sytem exampl
101, 60, 47, 116, 105, 116, 108, 101, 62, 10, 32, 32, // e</title>.
32, 32, 60, 108, 105, 110, 107, 32, 114, 101, 108, 61, // <link rel=
34, 115, 116, 121, 108, 101, 115, 104, 101, 101, 116, 34, // "stylesheet"
32, 104, 114, 101, 102, 61, 34, 115, 116, 121, 108, 101, // href="style
46, 99, 115, 115, 34, 32, 47, 62, 10, 32, 32, 60, // .css" />. <
47, 104, 101, 97, 100, 62, 10, 32, 32, 60, 98, 111, // /head>. <bo
100, 121, 62, 60, 47, 98, 111, 100, 121, 62, 10, 32, // dy></body>.
32, 60, 115, 99, 114, 105, 112, 116, 32, 116, 121, 112, // <script typ
101, 61, 34, 109, 111, 100, 117, 108, 101, 34, 32, 115, // e="module" s
114, 99, 61, 34, 109, 97, 105, 110, 46, 106, 115, 34, // rc="main.js"
62, 60, 47, 115, 99, 114, 105, 112, 116, 62, 10, 60, // ></script>.<
47, 104, 116, 109, 108, 62, 10, 0 // /html>.
};
static const unsigned char v2[] = {
31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 109, 97, // .......b..ma
105, 110, 46, 106, 115, 0, 165, 86, 237, 110, 219, 54, // in.js..V.n.6
20, 253, 239, 167, 184, 8, 6, 52, 65, 109, 41, 77, // .......4Am)M
246, 1, 52, 138, 1, 55, 93, 129, 20, 93, 61, 204, // ..4..7]..]=.
233, 218, 254, 43, 37, 210, 22, 91, 138, 84, 249, 97, // ...+%..[.T.a
205, 11, 242, 46, 125, 150, 62, 217, 14, 37, 217, 177, // ....}.>..%..
19, 103, 195, 218, 95, 166, 36, 222, 123, 15, 207, 185, // .g.._.$.{...
247, 208, 143, 130, 19, 228, 188, 149, 133, 127, 116, 54, // ..........t6
144, 85, 109, 172, 167, 107, 42, 135, 84, 250, 74, 13, // .Um..k*.T.J.
201, 10, 205, 133, 165, 27, 154, 91, 83, 209, 163, 36, // .......[S..$
173, 173, 96, 133, 79, 42, 169, 147, 143, 14, 33, 131, // ..`.O*....!.
65, 97, 180, 243, 244, 142, 206, 105, 30, 116, 225, 165, // Aa.....i.t..
209, 116, 120, 68, 215, 131, 1, 33, 218, 7, 171, 219, // .txD...!....
84, 31, 240, 152, 113, 185, 164, 66, 49, 231, 206, 15, // T...q..B1...
16, 229, 153, 212, 194, 30, 140, 241, 5, 223, 202, 147, // ............
245, 39, 39, 218, 44, 7, 227, 201, 179, 233, 155, 43, // .''.,......+
122, 51, 203, 210, 242, 164, 223, 181, 149, 193, 154, 166, // z3..........
143, 189, 155, 89, 141, 126, 217, 124, 193, 183, 122, 220, // ...Y.~.|..z.
45, 54, 111, 136, 46, 132, 99, 168, 79, 51, 51, 247, // -6o...c.O33.
13, 179, 130, 94, 121, 158, 144, 116, 84, 10, 198, 63, // ...^y..tT..?
7, 102, 189, 176, 130, 127, 253, 34, 53, 61, 15, 185, // .f....."5=..
146, 122, 72, 127, 136, 58, 174, 10, 50, 115, 186, 180, // .zH..:..2s..
66, 49, 205, 147, 219, 26, 105, 189, 83, 112, 231, 121, // B1....i.Sp.y
26, 44, 40, 54, 118, 69, 214, 24, 239, 40, 103, 197, // .,(6vE...(g.
39, 242, 134, 78, 142, 143, 127, 28, 82, 83, 10, 77, // '..N....RS.M
191, 25, 189, 48, 6, 82, 188, 21, 57, 205, 132, 93, // ...0.R..9..]
130, 243, 87, 50, 183, 204, 174, 190, 126, 225, 98, 41, // ..W2....~.b)
148, 169, 43, 161, 61, 242, 68, 108, 192, 154, 229, 118, // ..+.=.Dl...v
60, 216, 148, 152, 184, 189, 41, 22, 86, 52, 132, 51, // <.....).V4.3
212, 166, 14, 138, 89, 233, 87, 4, 216, 84, 49, 200, // ....Y.W..T1.
34, 56, 153, 184, 199, 151, 130, 230, 70, 41, 211, 72, // "8......F).H
189, 160, 149, 96, 214, 13, 99, 204, 201, 241, 147, 211, // ...`..c.....
13, 79, 13, 115, 36, 80, 27, 4, 184, 18, 145, 64, // .O.s$P.....@
31, 5, 148, 58, 8, 146, 56, 210, 54, 196, 88, 97, // ...:..8.6.Xa
3, 172, 182, 102, 41, 57, 90, 44, 212, 109, 107, 33, // ...f)9Z,.mk!
208, 128, 142, 37, 83, 1, 105, 138, 0, 94, 42, 97, // ...%S.i..^*a
221, 195, 76, 190, 21, 20, 245, 65, 158, 208, 150, 45, // ..L....A...-
217, 18, 111, 42, 28, 182, 77, 180, 201, 128, 67, 233, // ..o*..M...C.
21, 101, 114, 252, 2, 101, 130, 22, 244, 211, 241, 113, // .er..e.....q
150, 202, 49, 112, 86, 53, 211, 82, 56, 194, 25, 26, // ..1pV5.R8...
161, 84, 252, 173, 4, 151, 161, 106, 161, 186, 138, 225, // .T.....j....
157, 147, 127, 11, 202, 131, 67, 71, 58, 39, 182, 240, // ......CG:'..
16, 184, 44, 194, 134, 58, 244, 134, 138, 107, 52, 65, // ..,..:...k4A
44, 239, 140, 10, 177, 87, 93, 236, 29, 70, 53, 179, // ,....W]..F5.
128, 22, 64, 194, 220, 88, 10, 174, 13, 105, 9, 198, // ..@..X...i..
204, 96, 193, 252, 94, 153, 16, 139, 49, 228, 148, 175, // .`..^...1...
232, 245, 100, 54, 33, 150, 27, 102, 187, 192, 75, 141, // ..d6!..f..K.
78, 212, 44, 214, 96, 138, 102, 53, 43, 4, 205, 124, // N.,.`.f5+..|
251, 28, 195, 182, 96, 198, 221, 57, 52, 138, 194, 204, // ....`..94...
165, 173, 186, 61, 96, 76, 250, 100, 135, 212, 150, 214, // ...=`L.d....
153, 212, 200, 20, 53, 30, 110, 68, 46, 163, 200, 127, // ....5.nD....
129, 44, 14, 44, 81, 85, 144, 206, 3, 128, 71, 229, // .,.,QU....G.
208, 34, 210, 36, 64, 189, 214, 186, 61, 27, 151, 209, // .".$@...=...
59, 242, 224, 5, 137, 42, 23, 60, 70, 186, 245, 76, // ;....*.<F..L
197, 13, 37, 14, 210, 62, 52, 210, 151, 96, 5, 122, // ..%..>4..`.z
17, 96, 1, 163, 198, 148, 99, 119, 95, 227, 150, 170, // .`....cw_...
238, 196, 194, 71, 138, 175, 74, 244, 164, 235, 224, 175, // ...G..J.....
39, 61, 197, 168, 247, 102, 176, 94, 246, 139, 15, 103, // '=...f.^...g
131, 155, 179, 181, 31, 189, 255, 110, 63, 58, 189, 239, // .......n?:..
71, 155, 182, 187, 69, 109, 197, 83, 216, 211, 233, 55, // G...Em.S...7
219, 83, 22, 212, 150, 52, 153, 146, 219, 66, 81, 6, // .S...4...BQ.
85, 172, 152, 159, 31, 148, 222, 215, 238, 105, 154, 86, // U........i.V
125, 251, 36, 141, 75, 15, 198, 123, 154, 41, 75, 217, // }.$.K..{.)K.
78, 134, 17, 136, 189, 213, 166, 193, 62, 215, 53, 93, // N.......>.5]
228, 27, 52, 55, 198, 126, 138, 131, 175, 58, 183, 217, // ..47.~...:..
130, 146, 238, 96, 249, 79, 100, 75, 48, 152, 72, 3, // ...`.OdK0.H.
84, 127, 94, 76, 95, 99, 117, 31, 201, 196, 242, 32, // T.^L_cu....
181, 25, 181, 35, 233, 101, 174, 208, 177, 177, 211, 93, // ...#.e.....]
215, 29, 121, 144, 202, 143, 96, 61, 177, 125, 219, 166, // ..y...`=.}..
153, 94, 77, 40, 212, 156, 121, 225, 182, 51, 117, 30, // .^M(..y..3u.
166, 217, 66, 180, 134, 195, 153, 43, 219, 60, 223, 14, // ..B....+.<..
190, 138, 57, 18, 208, 1, 248, 213, 243, 126, 189, 151, // ..9......~..
74, 152, 5, 32, 142, 12, 28, 230, 210, 92, 209, 239, // J.. ........
138, 97, 52, 108, 245, 29, 165, 123, 13, 71, 198, 37, // .a4l...{.G.%
32, 102, 75, 212, 233, 108, 47, 2, 83, 11, 11, 246, // fK..l/.S...
160, 153, 91, 57, 47, 170, 214, 107, 96, 223, 163, 218, // ..[9/..k`...
52, 208, 181, 146, 133, 53, 177, 155, 45, 76, 29, 198, // 4....5..-L..
120, 23, 217, 255, 128, 182, 128, 42, 33, 143, 168, 210, // x......*!...
162, 243, 136, 180, 250, 232, 192, 208, 203, 253, 200, 54, // ...........6
109, 246, 146, 45, 217, 172, 176, 178, 246, 36, 244, 2, // m..-.....$..
83, 213, 98, 188, 72, 47, 30, 63, 126, 128, 168, 44, // S.b.H/.?~..,
189, 157, 131, 173, 17, 191, 63, 58, 63, 239, 222, 236, // ......?:?...
89, 62, 158, 238, 248, 112, 55, 144, 249, 238, 13, 188, // Y>...p7.....
59, 100, 237, 193, 37, 108, 102, 1, 30, 163, 213, 105, // ;d..%lf....i
184, 164, 47, 77, 192, 17, 209, 139, 240, 29, 156, 24, // ../M........
119, 74, 33, 97, 185, 235, 73, 191, 35, 107, 155, 131, // wJ!a..I.#k..
139, 90, 153, 85, 119, 29, 150, 65, 115, 220, 169, 109, // .Z.Uw..As..m
120, 37, 149, 106, 193, 192, 42, 37, 152, 107, 175, 224, // x%.j..*%.k..
46, 79, 116, 35, 161, 151, 210, 26, 29, 123, 247, 78, // .Ot#.....{.N
218, 7, 88, 248, 87, 163, 155, 212, 245, 142, 213, 161, // ..X.W.......
80, 237, 246, 249, 93, 86, 62, 25, 63, 99, 14, 255, // P...]V>.?c..
96, 126, 93, 235, 244, 66, 42, 209, 55, 17, 23, 21, // `~]..B*.7...
38, 22, 91, 6, 89, 95, 236, 135, 235, 242, 240, 221, // &.[.Y_......
209, 205, 160, 47, 186, 253, 250, 253, 230, 117, 15, 5, // .../.....u..
255, 29, 184, 105, 18, 163, 149, 97, 28, 112, 96, 184, // ...i...a.p`.
231, 227, 254, 207, 227, 97, 121, 8, 140, 71, 67, 226, // .....ay..GC.
112, 255, 120, 232, 36, 55, 124, 117, 116, 54, 248, 7, // p.x.$7|ut6..
71, 33, 75, 134, 124, 10, 0, 0, 0 // G!K.|...
};
static const unsigned char v3[] = {
39, 117, 115, 101, 32, 115, 116, 114, 105, 99, 116, 39, // 'use strict'
59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 104, // ;.import { h
44, 32, 104, 116, 109, 108, 44, 32, 114, 101, 110, 100, // , html, rend
@@ -774,7 +282,7 @@ static const unsigned char v3[] = {
112, 41, 44, 32, 100, 111, 99, 117, 109, 101, 110, 116, // p), document
46, 98, 111, 100, 121, 41, 59, 10, 0 // .body);.
};
static const unsigned char v4[] = {
static const unsigned char v3[] = {
118, 97, 114, 32, 101, 44, 110, 44, 95, 44, 116, 44, // var e,n,_,t,
111, 44, 114, 44, 117, 44, 108, 61, 123, 125, 44, 105, // o,r,u,l={},i
61, 91, 93, 44, 99, 61, 47, 97, 99, 105, 116, 124, // =[],c=/acit|
@@ -1876,147 +1384,7 @@ static const unsigned char v4[] = {
115, 101, 69, 114, 114, 111, 114, 66, 111, 117, 110, 100, // seErrorBound
97, 114, 121, 125, 59, 10, 0 // ary};.
};
static const unsigned char v5[] = {
60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 104, 116, // <!DOCTYPE ht
109, 108, 62, 10, 60, 104, 116, 109, 108, 32, 108, 97, // ml>.<html la
110, 103, 61, 34, 101, 110, 34, 62, 10, 32, 32, 60, // ng="en">. <
104, 101, 97, 100, 62, 10, 32, 32, 32, 32, 60, 109, // head>. <m
101, 116, 97, 32, 110, 97, 109, 101, 61, 34, 100, 101, // eta name="de
115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 99, // scription" c
111, 110, 116, 101, 110, 116, 61, 34, 77, 111, 110, 103, // ontent="Mong
111, 111, 115, 101, 32, 69, 109, 98, 101, 100, 100, 101, // oose Embedde
100, 32, 70, 105, 108, 101, 115, 121, 116, 101, 109, 32, // d Filesytem
101, 120, 97, 109, 112, 108, 101, 34, 32, 47, 62, 10, // example" />.
32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // <meta ht
116, 112, 45, 101, 113, 117, 105, 118, 61, 34, 67, 111, // tp-equiv="Co
110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 34, 32, // ntent-Type"
99, 111, 110, 116, 101, 110, 116, 61, 34, 116, 101, 120, // content="tex
116, 47, 104, 116, 109, 108, 59, 32, 99, 104, 97, 114, // t/html; char
115, 101, 116, 61, 85, 84, 70, 45, 56, 34, 62, 10, // set=UTF-8">.
32, 32, 32, 32, 60, 109, 101, 116, 97, 32, 104, 116, // <meta ht
116, 112, 45, 101, 113, 117, 105, 118, 61, 34, 88, 45, // tp-equiv="X-
85, 65, 45, 67, 111, 109, 112, 97, 116, 105, 98, 108, // UA-Compatibl
101, 34, 32, 99, 111, 110, 116, 101, 110, 116, 61, 34, // e" content="
73, 69, 61, 101, 100, 103, 101, 34, 62, 10, 32, 32, // IE=edge">.
32, 32, 60, 109, 101, 116, 97, 32, 110, 97, 109, 101, // <meta name
61, 34, 118, 105, 101, 119, 112, 111, 114, 116, 34, 32, // ="viewport"
99, 111, 110, 116, 101, 110, 116, 61, 34, 119, 105, 100, // content="wid
116, 104, 61, 100, 101, 118, 105, 99, 101, 45, 119, 105, // th=device-wi
100, 116, 104, 44, 32, 105, 110, 105, 116, 105, 97, 108, // dth, initial
45, 115, 99, 97, 108, 101, 61, 49, 34, 62, 10, 32, // -scale=1">.
32, 32, 32, 32, 32, 32, 32, 60, 116, 105, 116, 108, // <titl
101, 62, 77, 111, 110, 103, 111, 111, 115, 101, 32, 69, // e>Mongoose E
109, 98, 101, 100, 100, 101, 100, 32, 70, 105, 108, 101, // mbedded File
115, 121, 116, 101, 109, 32, 101, 120, 97, 109, 112, 108, // sytem exampl
101, 60, 47, 116, 105, 116, 108, 101, 62, 10, 32, 32, // e</title>.
32, 32, 60, 108, 105, 110, 107, 32, 114, 101, 108, 61, // <link rel=
34, 115, 116, 121, 108, 101, 115, 104, 101, 101, 116, 34, // "stylesheet"
32, 104, 114, 101, 102, 61, 34, 115, 116, 121, 108, 101, // href="style
46, 99, 115, 115, 34, 32, 47, 62, 10, 32, 32, 60, // .css" />. <
47, 104, 101, 97, 100, 62, 10, 32, 32, 60, 98, 111, // /head>. <bo
100, 121, 62, 60, 47, 98, 111, 100, 121, 62, 10, 32, // dy></body>.
32, 60, 115, 99, 114, 105, 112, 116, 32, 116, 121, 112, // <script typ
101, 61, 34, 109, 111, 100, 117, 108, 101, 34, 32, 115, // e="module" s
114, 99, 61, 34, 109, 97, 105, 110, 46, 106, 115, 34, // rc="main.js"
62, 60, 47, 115, 99, 114, 105, 112, 116, 62, 10, 60, // ></script>.<
47, 104, 116, 109, 108, 62, 10, 0 // /html>.
};
static const unsigned char v6[] = {
31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 105, 110, // .......b..in
100, 101, 120, 46, 104, 116, 109, 108, 0, 141, 145, 77, // dex.html...M
75, 3, 49, 16, 134, 239, 253, 21, 99, 206, 166, 139, // K.1.....c...
55, 193, 205, 130, 212, 22, 60, 136, 30, 90, 208, 99, // 7.....<..Z.c
154, 140, 205, 104, 62, 214, 205, 244, 99, 255, 189, 217, // ...h>...c...
110, 133, 5, 17, 60, 205, 7, 47, 15, 51, 239, 91, // n...<../.3.[
95, 61, 60, 47, 214, 111, 47, 75, 112, 28, 124, 51, // _=</.o/Kp.|3
171, 135, 2, 94, 199, 157, 18, 24, 69, 51, 3, 168, // ...^....E3..
29, 106, 59, 52, 165, 13, 200, 26, 162, 14, 168, 132, // .j;4........
197, 108, 58, 106, 153, 82, 20, 96, 82, 100, 140, 172, // .l:j.R.`Rd..
196, 83, 138, 187, 148, 50, 194, 50, 108, 209, 90, 180, // .S...2.2l.Z.
176, 34, 143, 185, 103, 12, 128, 39, 29, 90, 143, 2, // ."..g..'.Z..
170, 41, 205, 49, 183, 18, 191, 246, 116, 80, 98, 49, // .).1....tPb1
98, 228, 186, 111, 113, 2, 101, 60, 113, 53, 28, 118, // b..oq.e<q5.v
7, 198, 233, 46, 35, 171, 205, 122, 37, 111, 197, 95, // ....#..z%o._
156, 87, 185, 185, 151, 139, 20, 90, 205, 180, 245, 83, // .W.....Z...S
212, 227, 82, 161, 221, 161, 248, 253, 207, 129, 240, 216, // ..R.........
166, 142, 39, 226, 35, 89, 118, 202, 226, 129, 12, 202, // ..'.#Yv.....
243, 112, 13, 20, 137, 73, 123, 153, 141, 246, 168, 110, // .p...I{....n
46, 160, 51, 140, 137, 61, 54, 255, 112, 160, 174, 70, // ..3..=6.p..F
233, 120, 131, 167, 248, 9, 29, 122, 37, 50, 247, 69, // .x.....z%2.E
233, 16, 203, 17, 174, 195, 247, 203, 102, 110, 114, 190, // ........fnr.
152, 86, 87, 63, 97, 212, 219, 100, 251, 166, 174, 206, // .VW?a..d....
101, 152, 199, 52, 128, 139, 117, 74, 132, 100, 247, 195, // e..4..uJ.d..
223, 185, 51, 101, 208, 20, 231, 31, 89, 20, 245, 40, // ..3e....Y..(
42, 49, 87, 99, 220, 223, 14, 156, 225, 97, 255, 1, // *1Wc.....a..
0, 0, 0 // ..
};
static const unsigned char v7[] = {
31, 139, 8, 8, 219, 27, 244, 98, 0, 3, 115, 116, // .......b..st
121, 108, 101, 46, 99, 115, 115, 0, 117, 84, 203, 110, // yle.css.uT.n
219, 48, 16, 188, 251, 43, 88, 4, 5, 218, 32, 82, // .0...+X... R
44, 41, 178, 99, 249, 210, 91, 63, 162, 232, 129, 18, // ,).c..[?....
87, 54, 17, 138, 84, 73, 58, 118, 90, 248, 223, 187, // W6..TI:vZ...
164, 30, 164, 226, 228, 98, 75, 187, 163, 125, 204, 12, // .....bK..}..
121, 79, 254, 145, 90, 93, 18, 195, 255, 114, 121, 168, // yO..Z]...ry.
240, 89, 51, 208, 9, 134, 246, 228, 186, 58, 218, 78, // .Y3......:.N
60, 96, 140, 189, 33, 172, 163, 250, 192, 101, 69, 214, // <`..!....eE.
123, 210, 83, 198, 60, 28, 159, 143, 192, 15, 71, 91, // {.S.<.....G[
145, 108, 189, 254, 186, 39, 173, 146, 238, 121, 211, 95, // .l...'...y._
136, 161, 210, 36, 6, 52, 111, 93, 41, 3, 2, 26, // ...$.4o])...
251, 64, 184, 236, 79, 248, 39, 104, 13, 162, 170, 106, // .@..O.'h...j
104, 149, 134, 7, 98, 225, 98, 169, 6, 138, 109, 212, // h...b.b...m.
201, 10, 46, 161, 34, 82, 73, 216, 15, 195, 29, 41, // ...."RI....)
83, 231, 202, 5, 200, 23, 222, 245, 74, 91, 42, 237, // S.......J[*.
126, 28, 22, 219, 185, 110, 74, 112, 70, 238, 154, 166, // ~....nJpF...
89, 64, 174, 171, 70, 49, 108, 208, 107, 192, 218, 141, // Y@..F1l.k...
18, 10, 241, 119, 197, 182, 24, 70, 77, 90, 218, 113, // ...w...FMZ.q
241, 86, 145, 78, 73, 101, 122, 218, 192, 24, 63, 143, // .V.NIez...?.
91, 213, 74, 96, 139, 49, 136, 36, 225, 92, 166, 163, // [.J`.1.$....
66, 184, 88, 77, 155, 151, 131, 86, 39, 201, 176, 36, // B.XM...V'..$
99, 44, 230, 37, 205, 160, 195, 223, 2, 186, 105, 204, // c,.%......i.
68, 83, 198, 79, 198, 229, 114, 23, 189, 174, 166, 165, // DS.O..r.....
103, 82, 82, 252, 92, 73, 156, 51, 234, 150, 149, 253, // gRR..I.3....
229, 179, 77, 23, 13, 203, 161, 40, 86, 163, 213, 43, // ..M....(V..+
55, 220, 2, 115, 143, 180, 177, 252, 53, 222, 189, 44, // 7..s....5..,
189, 30, 115, 175, 197, 22, 0, 72, 0, 233, 184, 76, // ..s....H...L
206, 156, 217, 99, 69, 118, 88, 21, 193, 181, 69, 232, // ...cEvX...E.
138, 44, 193, 126, 130, 155, 229, 162, 149, 189, 63, 166, // .,.~......?.
190, 109, 139, 125, 155, 147, 54, 238, 173, 87, 92, 90, // .m.}..6..W.Z
228, 16, 75, 50, 110, 122, 65, 81, 2, 46, 157, 238, // ..K2nzAQ....
73, 45, 84, 243, 178, 216, 108, 131, 84, 122, 202, 62, // I-T...l.Tz.>
82, 102, 53, 76, 247, 11, 203, 208, 90, 0, 251, 237, // Rf5L....Z...
44, 132, 66, 114, 251, 230, 89, 9, 61, 233, 201, 42, // ,.Br..Y.=..*
183, 139, 233, 148, 178, 71, 132, 89, 141, 14, 229, 150, // .....G.Y....
43, 52, 53, 74, 74, 210, 220, 120, 102, 26, 108, 67, // +45JJ..xf.lC
113, 20, 29, 155, 158, 228, 107, 39, 196, 72, 139, 175, // q.....k'.H..
229, 176, 44, 105, 5, 92, 16, 56, 175, 225, 222, 199, // ..,i...8....
148, 55, 108, 148, 26, 28, 237, 6, 246, 244, 248, 163, // .7l.........
119, 163, 171, 55, 18, 98, 60, 203, 192, 102, 80, 68, // w..7.b<..fPD
241, 40, 117, 42, 213, 89, 211, 30, 17, 231, 35, 202, // .(u*.Y....#.
157, 120, 255, 186, 46, 46, 234, 1, 157, 57, 188, 87, // .x.......9.W
152, 65, 59, 139, 38, 160, 69, 34, 203, 208, 187, 220, // .A;.&.E"....
177, 91, 79, 69, 102, 220, 185, 35, 62, 81, 226, 29, // .[OEf..#>Q..
238, 219, 24, 60, 217, 220, 155, 41, 208, 149, 141, 51, // ...<...)...3
90, 213, 243, 6, 173, 205, 168, 69, 107, 166, 127, 148, // Z......Ek...
65, 88, 220, 35, 247, 7, 165, 252, 240, 160, 60, 185, // AX.#......<.
232, 80, 51, 209, 131, 236, 35, 212, 149, 30, 106, 45, // .P3...#...j-
253, 219, 210, 208, 245, 125, 178, 133, 33, 233, 70, 121, // .....}..!.Fy
159, 163, 224, 79, 197, 234, 241, 158, 252, 212, 72, 197, // ...O......H.
253, 163, 83, 224, 124, 43, 172, 251, 77, 28, 193, 21, // ..S.|+..M...
153, 105, 70, 139, 127, 126, 63, 170, 87, 208, 173, 192, // .iF..~?.W...
235, 43, 152, 6, 241, 73, 150, 59, 221, 6, 55, 13, // .+...I.;..7.
87, 231, 148, 200, 66, 98, 151, 165, 155, 77, 148, 90, // W...Bb...M.Z
135, 212, 115, 145, 22, 69, 72, 237, 66, 102, 91, 134, // ..s..EH.Bf[.
240, 115, 8, 111, 54, 139, 90, 219, 144, 41, 159, 23, // .s.o6.Z..)..
165, 54, 81, 38, 154, 171, 12, 225, 167, 229, 88, 79, // .6Q&......XO
33, 83, 44, 167, 42, 66, 38, 143, 166, 138, 87, 95, // !S,.*B&...W_
78, 21, 237, 62, 15, 245, 163, 3, 198, 41, 249, 22, // N..>.....)..
221, 74, 89, 145, 225, 105, 252, 142, 224, 15, 15, 235, // .JY..i......
64, 244, 132, 205, 183, 254, 228, 94, 227, 82, 244, 50, // @......^.R.2
95, 112, 249, 84, 201, 201, 61, 74, 185, 212, 5, 63, // _p.T..=J...?
252, 15, 225, 232, 67, 124, 39, 7, 0, 0, 0 // ....C|'...
};
static const unsigned char v8[] = {
static const unsigned char v4[] = {
42, 32, 123, 32, 98, 111, 120, 45, 115, 105, 122, 105, // * { box-sizi
110, 103, 58, 32, 98, 111, 114, 100, 101, 114, 45, 98, // ng: border-b
111, 120, 59, 32, 125, 10, 104, 116, 109, 108, 44, 32, // ox; }.html,
@@ -2178,14 +1546,10 @@ static const struct packed_file {
size_t size;
time_t mtime;
} packed_files[] = {
{"/web_root/preact.min.js.gz", v1, sizeof(v1), 1660165083},
{"/web_root/main.js.gz", v2, sizeof(v2), 1660165083},
{"/web_root/main.js", v3, sizeof(v3), 1660586478},
{"/web_root/preact.min.js", v4, sizeof(v4), 1660586478},
{"/web_root/index.html", v5, sizeof(v5), 1660586478},
{"/web_root/index.html.gz", v6, sizeof(v6), 1660165083},
{"/web_root/style.css.gz", v7, sizeof(v7), 1660165083},
{"/web_root/style.css", v8, sizeof(v8), 1660586478},
{"/web_root/index.html", v1, sizeof(v1), 1692212839},
{"/web_root/main.js", v2, sizeof(v2), 1692212839},
{"/web_root/preact.min.js", v3, sizeof(v3), 1692212839},
{"/web_root/style.css", v4, sizeof(v4), 1692212839},
{NULL, NULL, 0, 0}
};
@@ -2193,11 +1557,9 @@ static int scmp(const char *a, const char *b) {
while (*a && (*a == *b)) a++, b++;
return *(const unsigned char *) a - *(const unsigned char *) b;
}
const char *mg_unlist(size_t no);
const char *mg_unlist(size_t no) {
return packed_files[no].name;
}
const char *mg_unpack(const char *path, size_t *size, time_t *mtime);
const char *mg_unpack(const char *name, size_t *size, time_t *mtime) {
const struct packed_file *p;
for (p = packed_files; p->name != NULL; p++) {
@@ -7,4 +7,4 @@ component_compile_options(-DMG_ENABLE_LINES)
component_compile_options(-DMG_ENABLE_PACKED_FS)
component_compile_options(-DHTTP_URL="http://0.0.0.0:80")
component_compile_options(-DHTTPS_URL="https://0.0.0.0:443")
component_compile_options(-DMG_ENABLE_MBEDTLS=0) # change to '1' to enable TLS
component_compile_options(-DMG_TLS=MG_TLS_NONE) # change to 'MG_TLS_MBED' to enable TLS
@@ -27,7 +27,7 @@ static void cb2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = ev_data; // Print HTTP response
MG_INFO(("Fetched:\n%.*s", (int) hm->message.len, hm->message.ptr));
c->is_closing = 1;
c->is_draining = 1;
}
}
+27 -15
View File
@@ -1,8 +1,8 @@
// Copyright (c) 2020 Cesanta Software Limited
// All rights reserved
//
// Streaming upload example. Demonstrates how to use MG_EV_HTTP_CHUNK events
// to send large payload in smaller chunks. To test, use curl utility:
// Streaming upload example. Demonstrates how to use MG_EV_READ events
// to get large payload in smaller chunks. To test, use curl utility:
//
// curl http://localhost:8000/upload?name=a.txt --data-binary @large_file.txt
@@ -12,21 +12,33 @@
// /upload - Saves the next file chunk
// all other URI - serves web_root/ directory
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (ev == MG_EV_HTTP_CHUNK && mg_http_match_uri(hm, "/upload")) {
MG_INFO(("Got chunk len %lu", (unsigned long) hm->chunk.len));
MG_INFO(("Query string: [%.*s]", (int) hm->query.len, hm->query.ptr));
// MG_INFO(("Chunk data:\n%.*s", (int) hm->chunk.len, hm->chunk.ptr));
mg_http_delete_chunk(c, hm);
if (hm->chunk.len == 0) {
MG_INFO(("Last chunk received, sending response"));
mg_http_reply(c, 200, "", "ok (chunked)\n");
if (ev == MG_EV_READ) {
// Parse the incoming data ourselves. If we can parse the request,
// store two size_t variables in the c->data: expected len and recv len.
size_t *data = (size_t *) c->data;
if (data[0]) { // Already parsed, simply print received data
data[1] += c->recv.len;
MG_INFO(("Got chunk len %lu, %lu total", c->recv.len, data[1]));
c->recv.len = 0; // And cleanup the receive buffer. Streaming!
if (data[1] >= data[0]) mg_http_reply(c, 200, "", "ok\n");
} else {
struct mg_http_message hm;
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
if (n < 0) mg_error(c, "Bad response");
if (n > 0) {
if (mg_http_match_uri(&hm, "/upload")) {
MG_INFO(("Got chunk len %lu", c->recv.len - n));
data[0] = hm.body.len;
data[1] = c->recv.len - n;
if (data[1] >= data[0]) mg_http_reply(c, 200, "", "ok\n");
} else {
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
mg_http_serve_dir(c, &hm, &opts);
}
}
}
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
mg_http_serve_dir(c, hm, &opts);
}
(void) fn_data;
(void) fn_data, (void) ev_data;
}
int main(void) {
@@ -19,12 +19,10 @@
of RAM to buffer everything.
<br><br>
In order to upload large files to a memory-constrained system, use
<code>MG_EV_HTTP_CHUNK</code> on a server side. It fires when
a partial HTTP message has been received (or a chunk-encoded chunk).
Use <code>mg_http_delete_chunk()</code> to release chunk memory.
When 0-sized chunk is received, that's the end of the message.
Use <code>MG_MAX_RECV_SIZE</code> build constant to limit
maximum chunk size on a server side.
<code>MG_EV_READ</code> on a server side. It fires when
a partial HTTP message has been received. We discourage this method,
since the client can send chunked-encoded data. Instead, please
split the upload into smaller pieces and send sequentially.
<br><br>
In this example, JavaScript code uses "fetch()" browser API.
Uploaded file is not saved, but rather printed by server side.
+10 -3
View File
@@ -1,14 +1,16 @@
PROG ?= example # Program we are building
PACK ?= ./pack # Packing executable
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
PACK = pack.exe # Packing executable
CC = gcc # Use MinGW gcc compiler
CFLAGS += -lws2_32 # Link against Winsock library
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
@@ -23,7 +25,12 @@ $(PROG): $(SOURCES) # Build program from sources
$(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(OUT)
clean: # Cleanup. Delete built program and all build artifacts
$(DELETE) $(PROG) *.o *.obj *.exe *.dSYM mbedtls
$(DELETE) $(PROG) *.o *.obj *.exe *.dSYM mbedtls $(PACK)
# Generate packed filesystem for serving cert
packed_fs.c: $(wildcard certs/*) Makefile
$(CC) ../../test/pack.c -o $(PACK)
$(PACK) $(wildcard certs/*) > $@
# see https://mongoose.ws/tutorials/tls/#how-to-build for TLS build options
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+1
View File
@@ -0,0 +1 @@
../../../test/data/ca.pem
+3 -3
View File
@@ -28,9 +28,9 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
// Connected to server. Extract host name from URL
struct mg_str host = mg_url_host(s_url);
// If s_url is https://, tell client connection to use TLS
if (mg_url_is_ssl(s_url)) {
struct mg_tls_opts opts = {.ca = "ca.pem", .srvname = host};
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = mg_url_host(s_url)};
mg_tls_init(c, &opts);
}
@@ -49,7 +49,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
// Response is received. Print it
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
printf("%.*s", (int) hm->message.len, hm->message.ptr);
c->is_closing = 1; // Tell mongoose to close this connection
c->is_draining = 1; // Tell mongoose to close this connection
*(bool *) fn_data = true; // Tell event loop to stop
} else if (ev == MG_EV_ERROR) {
*(bool *) fn_data = true; // Error, tell event loop to stop
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -1,13 +1,13 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
#CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
// see tutorial at https://mongoose.ws/tutorials/http-proxy-client/
# See tutorial at https://mongoose.ws/tutorials/http-proxy-client/
ARGS ?= 167.235.63.238:3128 http://info.cern.ch/ # default call arguments
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+12 -9
View File
@@ -20,15 +20,17 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
} else if (ev == MG_EV_CONNECT) {
// Proxy TCP connection established. Send CONNECT request
struct mg_str host = mg_url_host(url);
if (mg_url_is_ssl(url)) {
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = host};
mg_tls_init(c, &opts);
}
// c->is_hexdumping = 1;
mg_printf(c, "CONNECT %.*s:%hu HTTP/1.1\r\nHost: %.*s:%hu\r\n\r\n",
(int) host.len, host.ptr, mg_url_port(url), (int) host.len,
host.ptr, mg_url_port(url));
// If target URL is SSL/TLS, command client connection to use TLS
if (mg_url_is_ssl(url)) {
struct mg_tls_opts opts = {.ca = "ca.pem"};
mg_tls_init(c, &opts);
}
} else if (!connected && ev == MG_EV_READ) {
struct mg_http_message hm;
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
@@ -40,10 +42,11 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
("Connected to proxy, status: %.*s", (int) hm.uri.len, hm.uri.ptr));
mg_iobuf_del(&c->recv, 0, n);
// Send request to the target server
mg_printf(c, "GET %s HTTP/1.0\r\n"
"Host: %.*s\r\n"
"\r\n",
mg_url_uri(url), (int) host.len, host.ptr);
mg_printf(c,
"GET %s HTTP/1.0\r\n"
"Host: %.*s\r\n"
"\r\n",
mg_url_uri(url), (int) host.len, host.ptr);
}
}
}
+1
View File
@@ -0,0 +1 @@
../http-client/packed_fs.c
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+43 -5
View File
@@ -18,17 +18,55 @@ static const char *s_http_addr = "http://0.0.0.0:8000"; // HTTP port
static const char *s_https_addr = "https://0.0.0.0:8443"; // HTTPS port
static const char *s_root_dir = ".";
// Self signed certificates
// https://mongoose.ws/documentation/tutorials/tls/#self-signed-certificates
#ifdef TLS_TWOWAY
static const char *s_tls_ca =
"-----BEGIN CERTIFICATE-----\n"
"MIIBqjCCAU+gAwIBAgIUESoOPGqMhf9uarzblVFwzrQweMcwCgYIKoZIzj0EAwIw\n"
"RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n"
"YTESMBAGA1UEAwwJVGVzdCBSb290MCAXDTIwMDUwOTIxNTE0NFoYDzIwNTAwNTA5\n"
"MjE1MTQ0WjBEMQswCQYDVQQGEwJJRTEPMA0GA1UEBwwGRHVibGluMRAwDgYDVQQK\n"
"DAdDZXNhbnRhMRIwEAYDVQQDDAlUZXN0IFJvb3QwWTATBgcqhkjOPQIBBggqhkjO\n"
"PQMBBwNCAAQsq9ECZiSW1xI+CVBP8VDuUehVA166sR2YsnJ5J6gbMQ1dUCH/QvLa\n"
"dBdeU7JlQcH8hN5KEbmM9BnZxMor6ussox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud\n"
"DwQEAwIBrjAKBggqhkjOPQQDAgNJADBGAiEAnHFsAIwGQQyRL81B04dH6d86Iq0l\n"
"fL8OKzndegxOaB0CIQCPwSIwEGFdURDqCC0CY2dnMrUGY5ZXu3hHCojZGS7zvg==\n"
"-----END CERTIFICATE-----\n";
#endif
static const char *s_tls_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIBhzCCASygAwIBAgIUbnMoVd8TtWH1T09dANkK2LU6IUswCgYIKoZIzj0EAwIw\n"
"RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\n"
"YTESMBAGA1UEAwwJVGVzdCBSb290MB4XDTIwMDUwOTIxNTE0OVoXDTMwMDUwOTIx\n"
"NTE0OVowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n"
"QgAEkuBGnInDN6l06zVVQ1VcrOvH5FDu9MC6FwJc2e201P8hEpq0Q/SJS2nkbSuW\n"
"H/wBTTBaeXN2uhlBzMUWK790KKMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gw\n"
"EwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAwRgIhAPo6xx7LjCdZ\n"
"QY133XvLjAgVFrlucOZHONFVQuDXZsjwAiEAzHBNligA08c5U3SySYcnkhurGg50\n"
"BllCI0eYQ9ggp/o=\n"
"-----END CERTIFICATE-----\n";
static const char *s_tls_key =
"-----BEGIN PRIVATE KEY-----\n"
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglNni0t9Dg9icgG8w\n"
"kbfxWSS+TuNgbtNybIQXcm3NHpmhRANCAASS4EacicM3qXTrNVVDVVys68fkUO70\n"
"wLoXAlzZ7bTU/yESmrRD9IlLaeRtK5Yf/AFNMFp5c3a6GUHMxRYrv3Qo\n"
"-----END PRIVATE KEY-----\n";
// We use the same event handler function for HTTP and HTTPS connections
// fn_data is NULL for plain HTTP, and non-NULL for HTTPS
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_ACCEPT && fn_data != NULL) {
struct mg_tls_opts opts = {
//.ca = "ca.pem", // Uncomment to enable two-way SSL
.cert = "server.pem", // Certificate PEM file
.certkey = "server.pem", // This pem contains both cert and key
};
#ifdef TLS_TWOWAY
.ca = mg_str(s_tls_ca),
#endif
.cert = mg_str(s_tls_cert),
.key = mg_str(s_tls_key)};
mg_tls_init(c, &opts);
} else if (ev == MG_EV_HTTP_MSG) {
}
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/api/stats")) {
// Print some statistics about currently established connections
+2 -2
View File
@@ -1,11 +1,11 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
CFLAGS_MONGOOSE += -DMG_IO_SIZE=128 -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_IO_SIZE=128 -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+5 -4
View File
@@ -10,7 +10,7 @@
#include "mongoose.h"
static const char *s_backend_url =
#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL
#if MG_TLS
"https://cesanta.com";
#else
"http://info.cern.ch";
@@ -37,7 +37,7 @@ static void forward_request(struct mg_http_message *hm,
}
static void fn2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_connection *c2 = fn_data;
struct mg_connection *c2 = (struct mg_connection *) fn_data;
if (ev == MG_EV_READ) {
// All incoming data from the backend, forward to the client
if (c2 != NULL) mg_send(c2, c->recv.buf, c->recv.len);
@@ -59,12 +59,13 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
mg_error(c, "Cannot create backend connection");
} else {
if (mg_url_is_ssl(s_backend_url)) {
struct mg_tls_opts opts = {.ca = "ca.pem"};
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = mg_url_host(s_backend_url)};
mg_tls_init(c2, &opts);
}
c->fn_data = c2;
forward_request(hm, c2);
c->is_resp = 0; // process further msgs in keep-alive connection
c->is_resp = 0; // process further msgs in keep-alive connection
c2->is_hexdumping = 1;
}
} else if (ev == MG_EV_CLOSE) {
+1
View File
@@ -0,0 +1 @@
../http-client/packed_fs.c
+2 -2
View File
@@ -1,11 +1,11 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+40 -29
View File
@@ -1,14 +1,12 @@
// Copyright (c) 2021 Cesanta Software Limited
// All rights reserved
//
// Example HTTP client.
// Instead of buffering the whole HTTP response in memory and wait for the
// MG_EV_HTTP_MSG event, this client catches MG_EV_HTTP_CHUNK events and
// prints them. This is useful to download large content without spooling
// everything to memory, or catch chunked content.
// Example streaming HTTP client.
// The default HTTP handler waits until the whole HTTP message is buffered in
// c->recv IO buffer. It can be large. This example shows how to receive
// a potentially large response in chunks by handling the MG_EV_READ events.
//
// You can change `s_url` from the command line by executing: ./example YOUR_URL
//
// To enable SSL/TLS, see https://mongoose.ws/tutorials/tls/#how-to-build
#include "mongoose.h"
@@ -21,13 +19,11 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_CONNECT) {
// Connected to server. Extract host name from URL
struct mg_str host = mg_url_host(s_url);
// If s_url is https://, tell client connection to use TLS
if (mg_url_is_ssl(s_url)) {
struct mg_tls_opts opts = {.ca = "ca.pem", .srvname = host};
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = host};
mg_tls_init(c, &opts);
}
// Send request
mg_printf(c,
"GET %s HTTP/1.1\r\n"
@@ -36,33 +32,48 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
"Host: %.*s\r\n"
"\r\n",
mg_url_uri(s_url), (int) host.len, host.ptr);
} else if (ev == MG_EV_HTTP_CHUNK) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
fwrite(hm->chunk.ptr, 1, hm->chunk.len, stdout);
// fprintf(stderr, "c %u\n", (unsigned) hm->chunk.len);
mg_http_delete_chunk(c, hm);
if (hm->chunk.len == 0) *(bool *) fn_data = true; // Last chunk
} else if (ev == MG_EV_HTTP_MSG) {
// Response is received. Print it
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
fwrite(hm->body.ptr, 1, hm->body.len, stdout);
c->is_closing = 1; // Tell mongoose to close this connection
*(bool *) fn_data = true; // Tell event loop to stop
} else if (ev == MG_EV_READ) {
// Parse the incoming data ourselves. If we can parse the request,
// store two size_t variables in the c->data: expected len and recv len.
size_t *data = (size_t *) c->data;
if (data[0]) { // Already parsed, simply print received data
data[1] += c->recv.len;
fwrite(c->recv.buf, 1, c->recv.len, stdout);
c->recv.len = 0; // And cleanup the receive buffer. Streming!
if (data[1] >= data[0]) * (bool *) fn_data = true;
} else {
struct mg_http_message hm;
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
if (n < 0) mg_error(c, "Bad response");
if (n > 0) {
fwrite(c->recv.buf + n, 1, c->recv.len - n, stdout); // Print body
data[0] = n + hm.body.len;
data[1] = c->recv.len;
c->recv.len = 0; // Cleanup receive buffer
if (data[1] >= data[0]) * (bool *) fn_data = true;
}
}
} else if (ev == MG_EV_CLOSE) {
*(bool *) fn_data = true; // tell event loop to stop
} else if (ev == MG_EV_ERROR) {
*(bool *) fn_data = true; // Error, tell event loop to stop
}
(void) ev_data;
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr; // Event manager
bool done = false; // Event handler flips it to true
const char *log_level = getenv("V"); // Log level
if (log_level == NULL) log_level = "3"; // If not set, set to DEBUG
mg_log_set(atoi(log_level)); // Set to 0 to disable debug log
if (argc > 1) s_url = argv[1]; // Use URL from command line
mg_mgr_init(&mgr); // Initialise event manager
struct mg_mgr mgr; // Event manager
bool done = false; // Event handler flips it to true
const char *log_level = getenv("V"); // Log level
mg_mgr_init(&mgr); // Initialise event manager
if (log_level == NULL) log_level = "2"; // If not set, set to DEBUG
mg_log_set(atoi(log_level)); // Set to 0 to disable debug log
if (argc > 1) s_url = argv[1]; // Use URL from command line
mg_http_connect(&mgr, s_url, fn, &done); // Create client connection
while (!done) mg_mgr_poll(&mgr, 1000); // Infinite event loop
mg_mgr_free(&mgr); // Free resources
return 0;
}
+1
View File
@@ -0,0 +1 @@
../http-client/packed_fs.c
@@ -0,0 +1,53 @@
CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion
CFLAGS += -Wformat-truncation -fno-common -Wconversion
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include
CFLAGS += -D__SAME54P20A__ -Icmsis_sam/include
CFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = main.c syscalls.c startup.c
# Mongoose-specific source code files and build options. See https://mongoose.ws/documentation/#build-options
SOURCES += mongoose.c net.c packed_fs.c
CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 -DMG_ENABLE_LINES=1
CFLAGS += -DMG_ENABLE_DRIVER_SAME54=1 -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 $(CFLAGS_EXTRA)
# Example specific build options. See README.md
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\"
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F
else
RM = rm -rf
endif
build: firmware.bin
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
firmware.elf: cmsis_core cmsis_sam hal.h link.ld Makefile $(SOURCES)
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) -o $@
flash: firmware.bin
bossac -p /dev/cu.usb* -w -v -b $<
cmsis_core:
git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
cmsis_sam:
curl -sL https://packs.download.microchip.com/Microchip.SAME54_DFP.3.8.234.pack -o $@.zip
mkdir $@ && cd $@ && unzip ../$@.zip
# Automated test via https://vcon.io/automated-firmware-tests/. Set VCON_API_KEY and update DEVICE_URL
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/9
update: firmware.bin
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$<
test update: CFLAGS += -DUART_DEBUG=USART1
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
clean:
$(RM) firmware.* cmsis_core cmsis_sam *.zip
@@ -0,0 +1,219 @@
// Copyright (c) 2022 Cesanta Software Limited
// SPDX-License-Identifier: MIT
//
// https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D5x-E5x-Family-Data-Sheet-DS60001507.pdf
// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf
#ifndef LED_PIN
#define LED_PIN PIN('C', 18)
#endif
#ifndef BUTTON_PIN
#define BUTTON_PIN PIN('B', 31)
#endif
#ifndef UART_DEBUG
#define UART_DEBUG USART1
#endif
#pragma once
#include <sam.h>
#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)
static inline void spin(volatile uint32_t count) {
while (count--) (void) 0;
}
static inline uint32_t clock_sys_freq(void) {
return 48000000U;
}
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 };
#define GPIO(N) ((port_group_registers_t *) (PORT_BASE_ADDRESS + 0x80 * (N)))
typedef port_group_registers_t GPIO_TypeDef;
static inline GPIO_TypeDef *gpio_bank(uint16_t pin) {
return GPIO(PINBANK(pin));
}
static inline void gpio_toggle(uint16_t pin) {
gpio_bank(pin)->PORT_OUTTGL = BIT(PINNO(pin));
}
static inline bool gpio_read(uint16_t pin) {
return gpio_bank(pin)->PORT_IN & BIT(PINNO(pin));
}
static inline void gpio_write(uint16_t pin, bool val) {
GPIO_TypeDef *gpio = gpio_bank(pin);
if (val) {
gpio->PORT_OUTSET = BIT(PINNO(pin));
} else {
gpio->PORT_OUTCLR = BIT(PINNO(pin));
}
}
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
uint8_t speed, uint8_t pull, uint8_t af) {
(void) type, (void) speed, (void) pull, (void) af;
GPIO_TypeDef *gpio = gpio_bank(pin);
uint32_t mask = BIT(PINNO(pin));
MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk;
if (mode == GPIO_MODE_INPUT) {
gpio->PORT_DIRCLR = mask;
} else {
gpio->PORT_DIRSET = mask;
}
}
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);
}
typedef sercom_usart_int_registers_t USART_TypeDef;
#define USART1 ((USART_TypeDef *) SERCOM0_BASE_ADDRESS)
#define USART2 ((USART_TypeDef *) SERCOM1_BASE_ADDRESS)
#define USART3 ((USART_TypeDef *) SERCOM2_BASE_ADDRESS)
static inline bool uart_init(USART_TypeDef *uart, unsigned long baud) {
uint16_t rx = 0, tx = 0; // Pins
uint8_t rx_mux = 0, tx_mux = 0;
if (uart == USART1) {
MCLK_REGS->MCLK_APBAMASK |= MCLK_APBAMASK_SERCOM0_Msk;
GCLK_REGS->GCLK_PCHCTRL[SERCOM0_GCLK_ID_CORE] =
GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN_Msk;
GCLK_REGS->GCLK_PCHCTRL[SERCOM0_GCLK_ID_SLOW] =
GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN_Msk;
tx = PIN('A', 4), rx = PIN('A', 5);
rx_mux = MUX_PA05D_SERCOM0_PAD1, tx_mux = MUX_PA04D_SERCOM0_PAD0;
} else if (uart == USART2) {
MCLK_REGS->MCLK_APBAMASK |= MCLK_APBAMASK_SERCOM1_Msk;
tx = PIN('C', 27), rx = PIN('C', 28);
} else if (uart == USART3) {
MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_SERCOM2_Msk;
tx = PIN('A', 9), rx = PIN('A', 8);
} else {
return false;
}
gpio_bank(rx)->PORT_WRCONFIG =
PORT_WRCONFIG_PMUX(rx_mux) | PORT_WRCONFIG_WRPMUX(1) |
PORT_WRCONFIG_PMUXEN(1) | PORT_WRCONFIG_WRPINCFG(1) | BIT(PINNO(rx));
gpio_bank(tx)->PORT_WRCONFIG =
PORT_WRCONFIG_PMUX(tx_mux) | PORT_WRCONFIG_WRPMUX(1) |
PORT_WRCONFIG_PMUXEN(1) | PORT_WRCONFIG_WRPINCFG(1) | BIT(PINNO(tx));
uart->SERCOM_CTRLA = SERCOM_USART_INT_CTRLA_DORD(1) |
SERCOM_USART_INT_CTRLA_MODE(1 /* INT_CLK */) |
SERCOM_USART_INT_CTRLA_RXPO(1 /* PAD1 */) |
SERCOM_USART_INT_CTRLA_TXPO(0 /* PAD0 */) |
SERCOM_USART_INT_CTRLA_SAMPR(1);
uart->SERCOM_BAUD = (uint16_t) (clock_sys_freq() / (16 * baud));
uart->SERCOM_CTRLB = SERCOM_USART_INT_CTRLB_RXEN(1) |
SERCOM_USART_INT_CTRLB_TXEN(1) |
SERCOM_USART_INT_CTRLB_CHSIZE(0);
while (uart->SERCOM_SYNCBUSY & SERCOM_USART_INT_SYNCBUSY_CTRLB_Msk) spin(1);
uart->SERCOM_CTRLA |= SERCOM_USART_INT_CTRLA_ENABLE(1);
while (uart->SERCOM_SYNCBUSY & SERCOM_USART_INT_SYNCBUSY_ENABLE_Msk) spin(1);
return true;
}
static inline void uart_write_byte(USART_TypeDef *uart, uint8_t byte) {
while (!(uart->SERCOM_INTFLAG & SERCOM_USART_INT_INTFLAG_DRE_Msk)) spin(1);
uart->SERCOM_DATA = byte;
}
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 bool uart_read_ready(USART_TypeDef *uart) {
return (uart->SERCOM_INTFLAG & SERCOM_USART_EXT_INTFLAG_RXC_Msk);
}
static inline uint8_t uart_read_byte(USART_TypeDef *uart) {
return (uint8_t) (uart->SERCOM_DATA & 255U);
}
static inline void rng_init(void) {
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_TRNG_Msk;
TRNG_REGS->TRNG_CTRLA = TRNG_CTRLA_ENABLE_Msk;
}
static inline uint32_t rng_read(void) {
while ((TRNG_REGS->TRNG_INTFLAG & TRNG_INTFLAG_DATARDY_Msk) == 0) spin(1);
return TRNG_REGS->TRNG_DATA;
}
#define UID_BASE_W0 0x008061FC // Word 0 location of the 128-bit chip ID
#define UID_BASE_W1_3 0x00806010 // Words 1-3 location of the 128-bit chip ID
#define UUID(n) ((n >= 0 && n <= 3) ? \
(((uint8_t *) UID_BASE_W0)[n]) : \
(((uint8_t *) UID_BASE_W1_3)[n - 4]))
#define GENERATE_LOCALLY_ADMINISTERED_MAC() \
{ \
2, UUID(0) ^ UUID(1) ^ UUID(2), UUID(3) ^ UUID(4) ^ UUID(5), \
UUID(6) ^ UUID(7) ^ UUID(8), UUID(9) ^ UUID(10) ^ UUID(11), \
UUID(12) ^ UUID(13) ^ UUID(14) ^ UUID(15) \
}
static inline bool timer_expired(volatile uint64_t *t, uint64_t prd,
uint64_t now) {
if (now + prd < *t) *t = 0; // Time wrapped? Reset timer
if (*t == 0) *t = now + prd; // Firt poll? Set expiration
if (*t > now) return false; // Not expired yet, return
*t = (now - *t) > prd ? now + prd : *t + prd; // Next expiration time
return true; // Expired, return true
}
static inline void clock_init(void) {
SCB->CPACR |= (15U << 20); // Enable FPU
SysTick_Config(clock_sys_freq() / 1000); // Sys tick every 1ms
}
static inline void gpio_set_irq_handler(uint16_t pin, void (*fn)(void *),
void *arg) {
(void) pin, (void) fn, (void) arg;
}
static inline void ethernet_init(void) {
uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15),
PIN('A', 17), PIN('A', 18), PIN('A', 19), PIN('C', 11),
PIN('C', 12), PIN('C', 20)};
uint32_t af[] = {MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0,
MUX_PA14L_GMAC_GTXCK, MUX_PA15L_GMAC_GRXER,
MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0,
MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC,
MUX_PC12L_GMAC_GMDIO, MUX_PC20L_GMAC_GRXDV};
MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk;
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
int bank = PINBANK(pins[i]), no = PINNO(pins[i]);
PORT_REGS->GROUP[bank].PORT_PINCFG[no] |= PORT_PINCFG_PMUXEN_Msk;
volatile uint8_t *m = &PORT_REGS->GROUP[bank].PORT_PMUX[no / 2], v = m[0];
if (no & 1) {
m[0] = (uint8_t) ((v & ~0xf0) | PORT_PMUX_PMUXO(af[i]));
} else {
m[0] = (uint8_t) ((v & ~0x0f) | PORT_PMUX_PMUXE(af[i]));
}
}
PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk;
PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk;
PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk;
// Reset PHY
uint16_t phy_pin = PIN('C', 21);
gpio_output(phy_pin);
gpio_write(phy_pin, false);
spin(999);
gpio_write(phy_pin, true);
spin(999);
}
@@ -0,0 +1,25 @@
ENTRY(Reset_Handler);
MEMORY {
flash(rx) : ORIGIN = 0x00000000, LENGTH = 1024k
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
}
_estack = ORIGIN(sram) + LENGTH(sram);
SECTIONS {
.vectors : { FILL(256) KEEP(*(.vectors)) } > flash
.text : { *(.text*) } > flash
.rodata : { *(.rodata*) } > flash
.data : {
_sdata = .;
*(.first_data)
*(.data SORT(.data.*))
_edata = .;
} > sram AT > flash
_sidata = LOADADDR(.data);
.bss : { _sbss = .; *(.bss SORT(.bss.*) COMMON) _ebss = .; } > sram
. = ALIGN(8);
_end = .;
}
@@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: 2022-2023 Cesanta Software Limited
// SPDX-License-Identifier: MIT
#include "hal.h"
#include "mongoose.h"
#include "net.h"
#define BLINK_PERIOD_MS 500 // LED blinking period in millis
#define LOG_PERIOD_MS 1000 // Info log period in millis
void SystemInit(void) { // Called automatically by startup code
clock_init();
rng_init();
}
static volatile uint64_t s_ticks; // Milliseconds since boot
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
s_ticks++;
}
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
return s_ticks; // Return number of milliseconds since boot
}
void mg_random(void *buf, size_t len) { // Use on-board RNG
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
uint32_t r = rng_read();
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
}
}
static void timer_fn(void *arg) {
struct mg_tcpip_if *ifp = arg; // show network stats
const char *names[] = {"down", "up", "req", "ready"};
MG_INFO(("Ethernet: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
ifp->ndrop, ifp->nerr));
}
int main(void) {
gpio_input(BUTTON_PIN);
gpio_output(LED_PIN);
uart_init(UART_DEBUG, 115200);
ethernet_init();
MG_INFO(("Starting, CPU freq %g MHz", (double) clock_sys_freq() / 1000000));
struct mg_mgr mgr; // Initialise
mg_mgr_init(&mgr); // Mongoose event manager
mg_log_set(MG_LL_DEBUG); // Set log level
// Initialise Mongoose network stack
struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 5};
struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC()/*{2, 3, 4, 5, 6, 7}*/,
// Uncomment below for static configuration:
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
// .mask = mg_htonl(MG_U32(255, 255, 255, 0)),
// .gw = mg_htonl(MG_U32(192, 168, 0, 1)),
.driver = &mg_tcpip_driver_same54,
.driver_data = &driver_data};
mg_tcpip_init(&mgr, &mif);
mg_timer_add(&mgr, LOG_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif);
MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac));
while (mif.state != MG_TCPIP_STATE_READY) {
mg_mgr_poll(&mgr, 0);
}
MG_INFO(("Initialising application..."));
web_init(&mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -0,0 +1 @@
../../../../mongoose.c
@@ -0,0 +1 @@
../../../../mongoose.h
@@ -0,0 +1 @@
../../../device-dashboard/net.c
@@ -0,0 +1 @@
../../../device-dashboard/net.h
@@ -0,0 +1 @@
../../../device-dashboard/packed_fs.c
@@ -0,0 +1,332 @@
// SPDX-FileCopyrightText: 2022-2023 Cesanta Software Limited
// SPDX-License-Identifier: MIT
#include "hal.h"
void Reset_Handler(void); // Defined below
void Dummy_Handler(void); // Defined below
void SysTick_Handler(void); // Defined in main.c
void SystemInit(void); // Defined in main.c, called by reset handler
void _estack(void); // Defined in link.ld
#define WEAK_ALIAS __attribute__((weak, alias("Default_Handler")))
WEAK_ALIAS void NMI_Handler(void);
WEAK_ALIAS void HardFault_Handler(void);
WEAK_ALIAS void MemoryManagement_Handler(void);
WEAK_ALIAS void BusFault_Handler(void);
WEAK_ALIAS void UsageFault_Handler(void);
WEAK_ALIAS void SVCall_Handler(void);
WEAK_ALIAS void DebugMonitor_Handler(void);
WEAK_ALIAS void PendSV_Handler(void);
WEAK_ALIAS void SysTick_Handler(void);
WEAK_ALIAS void PM_Handler(void);
WEAK_ALIAS void MCLK_Handler(void);
WEAK_ALIAS void OSCCTRL_XOSC0_Handler(void);
WEAK_ALIAS void OSCCTRL_XOSC1_Handler(void);
WEAK_ALIAS void OSCCTRL_DFLL_Handler(void);
WEAK_ALIAS void OSCCTRL_DPLL0_Handler(void);
WEAK_ALIAS void OSCCTRL_DPLL1_Handler(void);
WEAK_ALIAS void OSC32KCTRL_Handler(void);
WEAK_ALIAS void SUPC_OTHER_Handler(void);
WEAK_ALIAS void SUPC_BODDET_Handler(void);
WEAK_ALIAS void WDT_Handler(void);
WEAK_ALIAS void RTC_Handler(void);
WEAK_ALIAS void EIC_EXTINT_0_Handler(void);
WEAK_ALIAS void EIC_EXTINT_1_Handler(void);
WEAK_ALIAS void EIC_EXTINT_2_Handler(void);
WEAK_ALIAS void EIC_EXTINT_3_Handler(void);
WEAK_ALIAS void EIC_EXTINT_4_Handler(void);
WEAK_ALIAS void EIC_EXTINT_5_Handler(void);
WEAK_ALIAS void EIC_EXTINT_6_Handler(void);
WEAK_ALIAS void EIC_EXTINT_7_Handler(void);
WEAK_ALIAS void EIC_EXTINT_8_Handler(void);
WEAK_ALIAS void EIC_EXTINT_9_Handler(void);
WEAK_ALIAS void EIC_EXTINT_10_Handler(void);
WEAK_ALIAS void EIC_EXTINT_11_Handler(void);
WEAK_ALIAS void EIC_EXTINT_12_Handler(void);
WEAK_ALIAS void EIC_EXTINT_13_Handler(void);
WEAK_ALIAS void EIC_EXTINT_14_Handler(void);
WEAK_ALIAS void EIC_EXTINT_15_Handler(void);
WEAK_ALIAS void FREQM_Handler(void);
WEAK_ALIAS void NVMCTRL_0_Handler(void);
WEAK_ALIAS void NVMCTRL_1_Handler(void);
WEAK_ALIAS void DMAC_0_Handler(void);
WEAK_ALIAS void DMAC_1_Handler(void);
WEAK_ALIAS void DMAC_2_Handler(void);
WEAK_ALIAS void DMAC_3_Handler(void);
WEAK_ALIAS void DMAC_OTHER_Handler(void);
WEAK_ALIAS void EVSYS_0_Handler(void);
WEAK_ALIAS void EVSYS_1_Handler(void);
WEAK_ALIAS void EVSYS_2_Handler(void);
WEAK_ALIAS void EVSYS_3_Handler(void);
WEAK_ALIAS void EVSYS_OTHER_Handler(void);
WEAK_ALIAS void PAC_Handler(void);
WEAK_ALIAS void RAMECC_Handler(void);
WEAK_ALIAS void SERCOM0_0_Handler(void);
WEAK_ALIAS void SERCOM0_1_Handler(void);
WEAK_ALIAS void SERCOM0_2_Handler(void);
WEAK_ALIAS void SERCOM0_OTHER_Handler(void);
WEAK_ALIAS void SERCOM1_0_Handler(void);
WEAK_ALIAS void SERCOM1_1_Handler(void);
WEAK_ALIAS void SERCOM1_2_Handler(void);
WEAK_ALIAS void SERCOM1_OTHER_Handler(void);
WEAK_ALIAS void SERCOM2_0_Handler(void);
WEAK_ALIAS void SERCOM2_1_Handler(void);
WEAK_ALIAS void SERCOM2_2_Handler(void);
WEAK_ALIAS void SERCOM2_OTHER_Handler(void);
WEAK_ALIAS void SERCOM3_0_Handler(void);
WEAK_ALIAS void SERCOM3_1_Handler(void);
WEAK_ALIAS void SERCOM3_2_Handler(void);
WEAK_ALIAS void SERCOM3_OTHER_Handler(void);
WEAK_ALIAS void SERCOM4_0_Handler(void);
WEAK_ALIAS void SERCOM4_1_Handler(void);
WEAK_ALIAS void SERCOM4_2_Handler(void);
WEAK_ALIAS void SERCOM4_OTHER_Handler(void);
WEAK_ALIAS void SERCOM5_0_Handler(void);
WEAK_ALIAS void SERCOM5_1_Handler(void);
WEAK_ALIAS void SERCOM5_2_Handler(void);
WEAK_ALIAS void SERCOM5_OTHER_Handler(void);
WEAK_ALIAS void SERCOM6_0_Handler(void);
WEAK_ALIAS void SERCOM6_1_Handler(void);
WEAK_ALIAS void SERCOM6_2_Handler(void);
WEAK_ALIAS void SERCOM6_OTHER_Handler(void);
WEAK_ALIAS void SERCOM7_0_Handler(void);
WEAK_ALIAS void SERCOM7_1_Handler(void);
WEAK_ALIAS void SERCOM7_2_Handler(void);
WEAK_ALIAS void SERCOM7_OTHER_Handler(void);
WEAK_ALIAS void CAN0_Handler(void);
WEAK_ALIAS void CAN1_Handler(void);
WEAK_ALIAS void USB_OTHER_Handler(void);
WEAK_ALIAS void USB_SOF_HSOF_Handler(void);
WEAK_ALIAS void USB_TRCPT0_Handler(void);
WEAK_ALIAS void USB_TRCPT1_Handler(void);
WEAK_ALIAS void GMAC_Handler(void);
WEAK_ALIAS void TCC0_OTHER_Handler(void);
WEAK_ALIAS void TCC0_MC0_Handler(void);
WEAK_ALIAS void TCC0_MC1_Handler(void);
WEAK_ALIAS void TCC0_MC2_Handler(void);
WEAK_ALIAS void TCC0_MC3_Handler(void);
WEAK_ALIAS void TCC0_MC4_Handler(void);
WEAK_ALIAS void TCC0_MC5_Handler(void);
WEAK_ALIAS void TCC1_OTHER_Handler(void);
WEAK_ALIAS void TCC1_MC0_Handler(void);
WEAK_ALIAS void TCC1_MC1_Handler(void);
WEAK_ALIAS void TCC1_MC2_Handler(void);
WEAK_ALIAS void TCC1_MC3_Handler(void);
WEAK_ALIAS void TCC2_OTHER_Handler(void);
WEAK_ALIAS void TCC2_MC0_Handler(void);
WEAK_ALIAS void TCC2_MC1_Handler(void);
WEAK_ALIAS void TCC2_MC2_Handler(void);
WEAK_ALIAS void TCC3_OTHER_Handler(void);
WEAK_ALIAS void TCC3_MC0_Handler(void);
WEAK_ALIAS void TCC3_MC1_Handler(void);
WEAK_ALIAS void TCC4_OTHER_Handler(void);
WEAK_ALIAS void TCC4_MC0_Handler(void);
WEAK_ALIAS void TCC4_MC1_Handler(void);
WEAK_ALIAS void TC0_Handler(void);
WEAK_ALIAS void TC1_Handler(void);
WEAK_ALIAS void TC2_Handler(void);
WEAK_ALIAS void TC3_Handler(void);
WEAK_ALIAS void TC4_Handler(void);
WEAK_ALIAS void TC5_Handler(void);
WEAK_ALIAS void TC6_Handler(void);
WEAK_ALIAS void TC7_Handler(void);
WEAK_ALIAS void PDEC_OTHER_Handler(void);
WEAK_ALIAS void PDEC_MC0_Handler(void);
WEAK_ALIAS void PDEC_MC1_Handler(void);
WEAK_ALIAS void ADC0_OTHER_Handler(void);
WEAK_ALIAS void ADC0_RESRDY_Handler(void);
WEAK_ALIAS void ADC1_OTHER_Handler(void);
WEAK_ALIAS void ADC1_RESRDY_Handler(void);
WEAK_ALIAS void AC_Handler(void);
WEAK_ALIAS void DAC_OTHER_Handler(void);
WEAK_ALIAS void DAC_EMPTY_0_Handler(void);
WEAK_ALIAS void DAC_EMPTY_1_Handler(void);
WEAK_ALIAS void DAC_RESRDY_0_Handler(void);
WEAK_ALIAS void DAC_RESRDY_1_Handler(void);
WEAK_ALIAS void I2S_Handler(void);
WEAK_ALIAS void PCC_Handler(void);
WEAK_ALIAS void AES_Handler(void);
WEAK_ALIAS void TRNG_Handler(void);
WEAK_ALIAS void ICM_Handler(void);
WEAK_ALIAS void PUKCC_Handler(void);
WEAK_ALIAS void QSPI_Handler(void);
WEAK_ALIAS void SDHC0_Handler(void);
WEAK_ALIAS void SDHC1_Handler(void);
__attribute__((section(".vectors"))) void (*const tab[16 + 138])(void) = {
_estack,
Reset_Handler,
NMI_Handler,
HardFault_Handler,
MemoryManagement_Handler,
BusFault_Handler,
UsageFault_Handler,
NULL,
NULL,
NULL,
NULL,
SVCall_Handler,
DebugMonitor_Handler,
NULL,
PendSV_Handler,
SysTick_Handler,
PM_Handler, // 0 Power
MCLK_Handler, // 1 Main
OSCCTRL_XOSC0_Handler, // 2 Oscillators
OSCCTRL_XOSC1_Handler, // 3 Oscillators
OSCCTRL_DFLL_Handler, // 4 Oscillators
OSCCTRL_DPLL0_Handler, // 5 Oscillators
OSCCTRL_DPLL1_Handler, // 6 Oscillators
OSC32KCTRL_Handler, // 7 32kHz
SUPC_OTHER_Handler, // 8 Supply
SUPC_BODDET_Handler, // 9 Supply
WDT_Handler, // 10 Watchdog
RTC_Handler, // 11 Real-Time
EIC_EXTINT_0_Handler, // 12 External
EIC_EXTINT_1_Handler, // 13 External
EIC_EXTINT_2_Handler, // 14 External
EIC_EXTINT_3_Handler, // 15 External
EIC_EXTINT_4_Handler, // 16 External
EIC_EXTINT_5_Handler, // 17 External
EIC_EXTINT_6_Handler, // 18 External
EIC_EXTINT_7_Handler, // 19 External
EIC_EXTINT_8_Handler, // 20 External
EIC_EXTINT_9_Handler, // 21 External
EIC_EXTINT_10_Handler, // 22 External
EIC_EXTINT_11_Handler, // 23 External
EIC_EXTINT_12_Handler, // 24 External
EIC_EXTINT_13_Handler, // 25 External
EIC_EXTINT_14_Handler, // 26 External
EIC_EXTINT_15_Handler, // 27 External
FREQM_Handler, // 28 Frequency
NVMCTRL_0_Handler, // 29 Non-Volatile
NVMCTRL_1_Handler, // 30 Non-Volatile
DMAC_0_Handler, // 31 Direct
DMAC_1_Handler, // 32 Direct
DMAC_2_Handler, // 33 Direct
DMAC_3_Handler, // 34 Direct
DMAC_OTHER_Handler, // 35 Direct
EVSYS_0_Handler, // 36 Event
EVSYS_1_Handler, // 37 Event
EVSYS_2_Handler, // 38 Event
EVSYS_3_Handler, // 39 Event
EVSYS_OTHER_Handler, // 40 Event
PAC_Handler, // 41 Peripheral
0, // 42 Reserved
0, // 43 Reserved
0, // 44 Reserved
RAMECC_Handler, // 45 RAM
SERCOM0_0_Handler, // 46 Serial
SERCOM0_1_Handler, // 47 Serial
SERCOM0_2_Handler, // 48 Serial
SERCOM0_OTHER_Handler, // 49 Serial
SERCOM1_0_Handler, // 50 Serial
SERCOM1_1_Handler, // 51 Serial
SERCOM1_2_Handler, // 52 Serial
SERCOM1_OTHER_Handler, // 53 Serial
SERCOM2_0_Handler, // 54 Serial
SERCOM2_1_Handler, // 55 Serial
SERCOM2_2_Handler, // 56 Serial
SERCOM2_OTHER_Handler, // 57 Serial
SERCOM3_0_Handler, // 58 Serial
SERCOM3_1_Handler, // 59 Serial
SERCOM3_2_Handler, // 60 Serial
SERCOM3_OTHER_Handler, // 61 Serial
SERCOM4_0_Handler, // 62 Serial
SERCOM4_1_Handler, // 63 Serial
SERCOM4_2_Handler, // 64 Serial
SERCOM4_OTHER_Handler, // 65 Serial
SERCOM5_0_Handler, // 66 Serial
SERCOM5_1_Handler, // 67 Serial
SERCOM5_2_Handler, // 68 Serial
SERCOM5_OTHER_Handler, // 69 Serial
SERCOM6_0_Handler, // 70 Serial
SERCOM6_1_Handler, // 71 Serial
SERCOM6_2_Handler, // 72 Serial
SERCOM6_OTHER_Handler, // 73 Serial
SERCOM7_0_Handler, // 74 Serial
SERCOM7_1_Handler, // 75 Serial
SERCOM7_2_Handler, // 76 Serial
SERCOM7_OTHER_Handler, // 77 Serial
CAN0_Handler, // 78 Control
CAN1_Handler, // 79 Control
USB_OTHER_Handler, // 80 Universal
USB_SOF_HSOF_Handler, // 81 Universal
USB_TRCPT0_Handler, // 82 Universal
USB_TRCPT1_Handler, // 83 Universal
GMAC_Handler, // 84 Ethernet
TCC0_OTHER_Handler, // 85 Timer
TCC0_MC0_Handler, // 86 Timer
TCC0_MC1_Handler, // 87 Timer
TCC0_MC2_Handler, // 88 Timer
TCC0_MC3_Handler, // 89 Timer
TCC0_MC4_Handler, // 90 Timer
TCC0_MC5_Handler, // 91 Timer
TCC1_OTHER_Handler, // 92 Timer
TCC1_MC0_Handler, // 93 Timer
TCC1_MC1_Handler, // 94 Timer
TCC1_MC2_Handler, // 95 Timer
TCC1_MC3_Handler, // 96 Timer
TCC2_OTHER_Handler, // 97 Timer
TCC2_MC0_Handler, // 98 Timer
TCC2_MC1_Handler, // 99 Timer
TCC2_MC2_Handler, // 100 Timer
TCC3_OTHER_Handler, // 101 Timer
TCC3_MC0_Handler, // 102 Timer
TCC3_MC1_Handler, // 103 Timer
TCC4_OTHER_Handler, // 104 Timer
TCC4_MC0_Handler, // 105 Timer
TCC4_MC1_Handler, // 106 Timer
TC0_Handler, // 107 Basic
TC1_Handler, // 108 Basic
TC2_Handler, // 109 Basic
TC3_Handler, // 110 Basic
TC4_Handler, // 111 Basic
TC5_Handler, // 112 Basic
TC6_Handler, // 113 Basic
TC7_Handler, // 114 Basic
PDEC_OTHER_Handler, // 115 Quadrature
PDEC_MC0_Handler, // 116 Quadrature
PDEC_MC1_Handler, // 117 Quadrature
ADC0_OTHER_Handler, // 118 Analog
ADC0_RESRDY_Handler, // 119 Analog
ADC1_OTHER_Handler, // 120 Analog
ADC1_RESRDY_Handler, // 121 Analog
AC_Handler, // 122 Analog
DAC_OTHER_Handler, // 123 Digital-to-Analog
DAC_EMPTY_0_Handler, // 124 Digital-to-Analog
DAC_EMPTY_1_Handler, // 125 Digital-to-Analog
DAC_RESRDY_0_Handler, // 126 Digital-to-Analog
DAC_RESRDY_1_Handler, // 127 Digital-to-Analog
I2S_Handler, // 128 Inter-IC
PCC_Handler, // 129 Parallel
AES_Handler, // 130 Advanced
TRNG_Handler, // 131 True
ICM_Handler, // 132 Integrity
PUKCC_Handler, // 133 PUblic-Key
QSPI_Handler, // 134 Quad
SDHC0_Handler, // 135 SD/MMC
SDHC1_Handler // 136 SD/MMC
};
__attribute__((naked, noreturn)) void Reset_Handler(void) {
// Clear BSS section, and copy data section from flash to RAM
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++;
SCB->VTOR = (uint32_t) &tab;
SystemInit();
// Call main()
extern void main(void);
main();
for (;;) (void) 0; // Infinite loop
}
void Default_Handler(void) {
for (;;) (void) 0;
}
@@ -0,0 +1,89 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include <sys/stat.h>
#include "hal.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(UART_DEBUG, 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;
}
void _init(void) {
}
@@ -0,0 +1,54 @@
CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion
CFLAGS += -Wformat-truncation -fno-common -Wconversion
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include
CFLAGS += -D__SAME54P20A__ -Icmsis_sam/include
CFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = main.c syscalls.c startup.c
# Mongoose-specific source code files and build options. See https://mongoose.ws/documentation/#build-options
SOURCES += mongoose.c
CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 -DMG_ENABLE_LINES=1
CFLAGS += -DMG_ENABLE_DRIVER_SAME54=1 -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 $(CFLAGS_EXTRA)
# Example specific build options. See README.md
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\"
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F
else
RM = rm -rf
endif
build: firmware.bin
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
firmware.elf: cmsis_core cmsis_sam hal.h link.ld Makefile $(SOURCES)
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) -o $@
flash: firmware.bin
bossac -p /dev/cu.usb* -w -v -b $<
cmsis_core:
git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
cmsis_sam:
curl -sL https://packs.download.microchip.com/Microchip.SAME54_DFP.3.8.234.pack -o $@.zip
mkdir $@ && cd $@ && unzip ../$@.zip
# Automated test via https://vcon.io/automated-firmware-tests/. Set VCON_API_KEY and update DEVICE_URL
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/9
update: firmware.bin
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$<
test update: CFLAGS += -DUART_DEBUG=USART1
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
grep 'RECEIVED hello' /tmp/output.txt # Check for MQTT success
clean:
$(RM) firmware.* cmsis_core cmsis_sam *.zip
@@ -0,0 +1,219 @@
// Copyright (c) 2022 Cesanta Software Limited
// SPDX-License-Identifier: MIT
//
// https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D5x-E5x-Family-Data-Sheet-DS60001507.pdf
// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf
#ifndef LED_PIN
#define LED_PIN PIN('C', 18)
#endif
#ifndef BUTTON_PIN
#define BUTTON_PIN PIN('B', 31)
#endif
#ifndef UART_DEBUG
#define UART_DEBUG USART1
#endif
#pragma once
#include <sam.h>
#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)
static inline void spin(volatile uint32_t count) {
while (count--) (void) 0;
}
static inline uint32_t clock_sys_freq(void) {
return 48000000U;
}
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 };
#define GPIO(N) ((port_group_registers_t *) (PORT_BASE_ADDRESS + 0x80 * (N)))
typedef port_group_registers_t GPIO_TypeDef;
static inline GPIO_TypeDef *gpio_bank(uint16_t pin) {
return GPIO(PINBANK(pin));
}
static inline void gpio_toggle(uint16_t pin) {
gpio_bank(pin)->PORT_OUTTGL = BIT(PINNO(pin));
}
static inline bool gpio_read(uint16_t pin) {
return gpio_bank(pin)->PORT_IN & BIT(PINNO(pin));
}
static inline void gpio_write(uint16_t pin, bool val) {
GPIO_TypeDef *gpio = gpio_bank(pin);
if (val) {
gpio->PORT_OUTSET = BIT(PINNO(pin));
} else {
gpio->PORT_OUTCLR = BIT(PINNO(pin));
}
}
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
uint8_t speed, uint8_t pull, uint8_t af) {
(void) type, (void) speed, (void) pull, (void) af;
GPIO_TypeDef *gpio = gpio_bank(pin);
uint32_t mask = BIT(PINNO(pin));
MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk;
if (mode == GPIO_MODE_INPUT) {
gpio->PORT_DIRCLR = mask;
} else {
gpio->PORT_DIRSET = mask;
}
}
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);
}
typedef sercom_usart_int_registers_t USART_TypeDef;
#define USART1 ((USART_TypeDef *) SERCOM0_BASE_ADDRESS)
#define USART2 ((USART_TypeDef *) SERCOM1_BASE_ADDRESS)
#define USART3 ((USART_TypeDef *) SERCOM2_BASE_ADDRESS)
static inline bool uart_init(USART_TypeDef *uart, unsigned long baud) {
uint16_t rx = 0, tx = 0; // Pins
uint8_t rx_mux = 0, tx_mux = 0;
if (uart == USART1) {
MCLK_REGS->MCLK_APBAMASK |= MCLK_APBAMASK_SERCOM0_Msk;
GCLK_REGS->GCLK_PCHCTRL[SERCOM0_GCLK_ID_CORE] =
GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN_Msk;
GCLK_REGS->GCLK_PCHCTRL[SERCOM0_GCLK_ID_SLOW] =
GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN_Msk;
tx = PIN('A', 4), rx = PIN('A', 5);
rx_mux = MUX_PA05D_SERCOM0_PAD1, tx_mux = MUX_PA04D_SERCOM0_PAD0;
} else if (uart == USART2) {
MCLK_REGS->MCLK_APBAMASK |= MCLK_APBAMASK_SERCOM1_Msk;
tx = PIN('C', 27), rx = PIN('C', 28);
} else if (uart == USART3) {
MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_SERCOM2_Msk;
tx = PIN('A', 9), rx = PIN('A', 8);
} else {
return false;
}
gpio_bank(rx)->PORT_WRCONFIG =
PORT_WRCONFIG_PMUX(rx_mux) | PORT_WRCONFIG_WRPMUX(1) |
PORT_WRCONFIG_PMUXEN(1) | PORT_WRCONFIG_WRPINCFG(1) | BIT(PINNO(rx));
gpio_bank(tx)->PORT_WRCONFIG =
PORT_WRCONFIG_PMUX(tx_mux) | PORT_WRCONFIG_WRPMUX(1) |
PORT_WRCONFIG_PMUXEN(1) | PORT_WRCONFIG_WRPINCFG(1) | BIT(PINNO(tx));
uart->SERCOM_CTRLA = SERCOM_USART_INT_CTRLA_DORD(1) |
SERCOM_USART_INT_CTRLA_MODE(1 /* INT_CLK */) |
SERCOM_USART_INT_CTRLA_RXPO(1 /* PAD1 */) |
SERCOM_USART_INT_CTRLA_TXPO(0 /* PAD0 */) |
SERCOM_USART_INT_CTRLA_SAMPR(1);
uart->SERCOM_BAUD = (uint16_t) (clock_sys_freq() / (16 * baud));
uart->SERCOM_CTRLB = SERCOM_USART_INT_CTRLB_RXEN(1) |
SERCOM_USART_INT_CTRLB_TXEN(1) |
SERCOM_USART_INT_CTRLB_CHSIZE(0);
while (uart->SERCOM_SYNCBUSY & SERCOM_USART_INT_SYNCBUSY_CTRLB_Msk) spin(1);
uart->SERCOM_CTRLA |= SERCOM_USART_INT_CTRLA_ENABLE(1);
while (uart->SERCOM_SYNCBUSY & SERCOM_USART_INT_SYNCBUSY_ENABLE_Msk) spin(1);
return true;
}
static inline void uart_write_byte(USART_TypeDef *uart, uint8_t byte) {
while (!(uart->SERCOM_INTFLAG & SERCOM_USART_INT_INTFLAG_DRE_Msk)) spin(1);
uart->SERCOM_DATA = byte;
}
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 bool uart_read_ready(USART_TypeDef *uart) {
return (uart->SERCOM_INTFLAG & SERCOM_USART_EXT_INTFLAG_RXC_Msk);
}
static inline uint8_t uart_read_byte(USART_TypeDef *uart) {
return (uint8_t) (uart->SERCOM_DATA & 255U);
}
static inline void rng_init(void) {
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_TRNG_Msk;
TRNG_REGS->TRNG_CTRLA = TRNG_CTRLA_ENABLE_Msk;
}
static inline uint32_t rng_read(void) {
while ((TRNG_REGS->TRNG_INTFLAG & TRNG_INTFLAG_DATARDY_Msk) == 0) spin(1);
return TRNG_REGS->TRNG_DATA;
}
#define UID_BASE_W0 0x008061FC // Word 0 location of the 128-bit chip ID
#define UID_BASE_W1_3 0x00806010 // Words 1-3 location of the 128-bit chip ID
#define UUID(n) ((n >= 0 && n <= 3) ? \
(((uint8_t *) UID_BASE_W0)[n]) : \
(((uint8_t *) UID_BASE_W1_3)[n - 4]))
#define GENERATE_LOCALLY_ADMINISTERED_MAC() \
{ \
2, UUID(0) ^ UUID(1) ^ UUID(2), UUID(3) ^ UUID(4) ^ UUID(5), \
UUID(6) ^ UUID(7) ^ UUID(8), UUID(9) ^ UUID(10) ^ UUID(11), \
UUID(12) ^ UUID(13) ^ UUID(14) ^ UUID(15) \
}
static inline bool timer_expired(volatile uint64_t *t, uint64_t prd,
uint64_t now) {
if (now + prd < *t) *t = 0; // Time wrapped? Reset timer
if (*t == 0) *t = now + prd; // Firt poll? Set expiration
if (*t > now) return false; // Not expired yet, return
*t = (now - *t) > prd ? now + prd : *t + prd; // Next expiration time
return true; // Expired, return true
}
static inline void clock_init(void) {
SCB->CPACR |= (15U << 20); // Enable FPU
SysTick_Config(clock_sys_freq() / 1000); // Sys tick every 1ms
}
static inline void gpio_set_irq_handler(uint16_t pin, void (*fn)(void *),
void *arg) {
(void) pin, (void) fn, (void) arg;
}
static inline void ethernet_init(void) {
uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15),
PIN('A', 17), PIN('A', 18), PIN('A', 19), PIN('C', 11),
PIN('C', 12), PIN('C', 20)};
uint32_t af[] = {MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0,
MUX_PA14L_GMAC_GTXCK, MUX_PA15L_GMAC_GRXER,
MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0,
MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC,
MUX_PC12L_GMAC_GMDIO, MUX_PC20L_GMAC_GRXDV};
MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk;
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
int bank = PINBANK(pins[i]), no = PINNO(pins[i]);
PORT_REGS->GROUP[bank].PORT_PINCFG[no] |= PORT_PINCFG_PMUXEN_Msk;
volatile uint8_t *m = &PORT_REGS->GROUP[bank].PORT_PMUX[no / 2], v = m[0];
if (no & 1) {
m[0] = (uint8_t) ((v & ~0xf0) | PORT_PMUX_PMUXO(af[i]));
} else {
m[0] = (uint8_t) ((v & ~0x0f) | PORT_PMUX_PMUXE(af[i]));
}
}
PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk;
PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk;
PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk;
// Reset PHY
uint16_t phy_pin = PIN('C', 21);
gpio_output(phy_pin);
gpio_write(phy_pin, false);
spin(999);
gpio_write(phy_pin, true);
spin(999);
}
@@ -0,0 +1,25 @@
ENTRY(Reset_Handler);
MEMORY {
flash(rx) : ORIGIN = 0x00000000, LENGTH = 1024k
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
}
_estack = ORIGIN(sram) + LENGTH(sram);
SECTIONS {
.vectors : { FILL(256) KEEP(*(.vectors)) } > flash
.text : { *(.text*) } > flash
.rodata : { *(.rodata*) } > flash
.data : {
_sdata = .;
*(.first_data)
*(.data SORT(.data.*))
_edata = .;
} > sram AT > flash
_sidata = LOADADDR(.data);
.bss : { _sbss = .; *(.bss SORT(.bss.*) COMMON) _ebss = .; } > sram
. = ALIGN(8);
_end = .;
}
@@ -0,0 +1,120 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
#include "hal.h"
#include "mongoose.h"
static const char *s_url = "mqtt://broker.hivemq.com:1883";
static const char *s_sub_topic = "mg/+/test"; // Publish topic
static const char *s_pub_topic = "mg/clnt/test"; // Subscribe topic
static const uint8_t s_qos = 1; // MQTT QoS
static struct mg_connection *s_conn; // Client connection
void SystemInit(void) { // Called automatically by startup code
clock_init();
rng_init();
}
static volatile uint64_t s_ticks; // Milliseconds since boot
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
s_ticks++;
}
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
return s_ticks; // Return number of milliseconds since boot
}
void mg_random(void *buf, size_t len) { // Use on-board RNG
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
uint32_t r = rng_read();
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
}
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_OPEN) {
MG_INFO(("%lu CREATED", c->id));
// c->is_hexdumping = 1;
} else if (ev == MG_EV_ERROR) {
// On error, log error message
MG_ERROR(("%lu ERROR %s", c->id, (char *) ev_data));
} else if (ev == MG_EV_MQTT_OPEN) {
// MQTT connect is successful
struct mg_str subt = mg_str(s_sub_topic);
struct mg_str pubt = mg_str(s_pub_topic), data = mg_str("hello");
MG_INFO(("%lu CONNECTED to %s", c->id, s_url));
struct mg_mqtt_opts sub_opts;
memset(&sub_opts, 0, sizeof(sub_opts));
sub_opts.topic = subt;
sub_opts.qos = s_qos;
mg_mqtt_sub(c, &sub_opts);
MG_INFO(("%lu SUBSCRIBED to %.*s", c->id, (int) subt.len, subt.ptr));
struct mg_mqtt_opts pub_opts;
memset(&pub_opts, 0, sizeof(pub_opts));
pub_opts.topic = pubt;
pub_opts.message = data;
pub_opts.qos = s_qos, pub_opts.retain = false;
mg_mqtt_pub(c, &pub_opts);
MG_INFO(("%lu PUBLISHED %.*s -> %.*s", c->id, (int) data.len, data.ptr,
(int) pubt.len, pubt.ptr));
} else if (ev == MG_EV_MQTT_MSG) {
// When we get echo response, print it
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
MG_INFO(("%lu RECEIVED %.*s <- %.*s", c->id, (int) mm->data.len,
mm->data.ptr, (int) mm->topic.len, mm->topic.ptr));
} else if (ev == MG_EV_CLOSE) {
MG_INFO(("%lu CLOSED", c->id));
s_conn = NULL; // Mark that we're closed
}
(void) fn_data;
}
// Timer function - recreate client connection if it is closed
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
struct mg_mqtt_opts opts = {.clean = true,
.qos = s_qos,
.topic = mg_str(s_pub_topic),
.version = 4,
.message = mg_str("bye")};
if (s_conn == NULL) s_conn = mg_mqtt_connect(mgr, s_url, &opts, fn, NULL);
}
int main(void) {
gpio_input(BUTTON_PIN);
gpio_output(LED_PIN);
uart_init(UART_DEBUG, 115200);
ethernet_init();
MG_INFO(("Starting, CPU freq %g MHz", (double) clock_sys_freq() / 1000000));
struct mg_mgr mgr; // Initialise
mg_mgr_init(&mgr); // Mongoose event manager
mg_log_set(MG_LL_DEBUG); // Set log level
// Initialise Mongoose network stack
struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 5};
struct mg_tcpip_if mif = {
.mac = GENERATE_LOCALLY_ADMINISTERED_MAC() /*{2, 3, 4, 5, 6, 7}*/,
// Uncomment below for static configuration:
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
// .mask = mg_htonl(MG_U32(255, 255, 255, 0)),
// .gw = mg_htonl(MG_U32(192, 168, 0, 1)),
.driver = &mg_tcpip_driver_same54,
.driver_data = &driver_data};
mg_tcpip_init(&mgr, &mif);
MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac));
while (mif.state != MG_TCPIP_STATE_READY) {
mg_mgr_poll(&mgr, 0);
}
MG_INFO(("Initialising application..."));
mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, &mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -0,0 +1 @@
../../../../mongoose.c
@@ -0,0 +1 @@
../../../../mongoose.h
@@ -0,0 +1,332 @@
// SPDX-FileCopyrightText: 2022-2023 Cesanta Software Limited
// SPDX-License-Identifier: MIT
#include "hal.h"
void Reset_Handler(void); // Defined below
void Dummy_Handler(void); // Defined below
void SysTick_Handler(void); // Defined in main.c
void SystemInit(void); // Defined in main.c, called by reset handler
void _estack(void); // Defined in link.ld
#define WEAK_ALIAS __attribute__((weak, alias("Default_Handler")))
WEAK_ALIAS void NMI_Handler(void);
WEAK_ALIAS void HardFault_Handler(void);
WEAK_ALIAS void MemoryManagement_Handler(void);
WEAK_ALIAS void BusFault_Handler(void);
WEAK_ALIAS void UsageFault_Handler(void);
WEAK_ALIAS void SVCall_Handler(void);
WEAK_ALIAS void DebugMonitor_Handler(void);
WEAK_ALIAS void PendSV_Handler(void);
WEAK_ALIAS void SysTick_Handler(void);
WEAK_ALIAS void PM_Handler(void);
WEAK_ALIAS void MCLK_Handler(void);
WEAK_ALIAS void OSCCTRL_XOSC0_Handler(void);
WEAK_ALIAS void OSCCTRL_XOSC1_Handler(void);
WEAK_ALIAS void OSCCTRL_DFLL_Handler(void);
WEAK_ALIAS void OSCCTRL_DPLL0_Handler(void);
WEAK_ALIAS void OSCCTRL_DPLL1_Handler(void);
WEAK_ALIAS void OSC32KCTRL_Handler(void);
WEAK_ALIAS void SUPC_OTHER_Handler(void);
WEAK_ALIAS void SUPC_BODDET_Handler(void);
WEAK_ALIAS void WDT_Handler(void);
WEAK_ALIAS void RTC_Handler(void);
WEAK_ALIAS void EIC_EXTINT_0_Handler(void);
WEAK_ALIAS void EIC_EXTINT_1_Handler(void);
WEAK_ALIAS void EIC_EXTINT_2_Handler(void);
WEAK_ALIAS void EIC_EXTINT_3_Handler(void);
WEAK_ALIAS void EIC_EXTINT_4_Handler(void);
WEAK_ALIAS void EIC_EXTINT_5_Handler(void);
WEAK_ALIAS void EIC_EXTINT_6_Handler(void);
WEAK_ALIAS void EIC_EXTINT_7_Handler(void);
WEAK_ALIAS void EIC_EXTINT_8_Handler(void);
WEAK_ALIAS void EIC_EXTINT_9_Handler(void);
WEAK_ALIAS void EIC_EXTINT_10_Handler(void);
WEAK_ALIAS void EIC_EXTINT_11_Handler(void);
WEAK_ALIAS void EIC_EXTINT_12_Handler(void);
WEAK_ALIAS void EIC_EXTINT_13_Handler(void);
WEAK_ALIAS void EIC_EXTINT_14_Handler(void);
WEAK_ALIAS void EIC_EXTINT_15_Handler(void);
WEAK_ALIAS void FREQM_Handler(void);
WEAK_ALIAS void NVMCTRL_0_Handler(void);
WEAK_ALIAS void NVMCTRL_1_Handler(void);
WEAK_ALIAS void DMAC_0_Handler(void);
WEAK_ALIAS void DMAC_1_Handler(void);
WEAK_ALIAS void DMAC_2_Handler(void);
WEAK_ALIAS void DMAC_3_Handler(void);
WEAK_ALIAS void DMAC_OTHER_Handler(void);
WEAK_ALIAS void EVSYS_0_Handler(void);
WEAK_ALIAS void EVSYS_1_Handler(void);
WEAK_ALIAS void EVSYS_2_Handler(void);
WEAK_ALIAS void EVSYS_3_Handler(void);
WEAK_ALIAS void EVSYS_OTHER_Handler(void);
WEAK_ALIAS void PAC_Handler(void);
WEAK_ALIAS void RAMECC_Handler(void);
WEAK_ALIAS void SERCOM0_0_Handler(void);
WEAK_ALIAS void SERCOM0_1_Handler(void);
WEAK_ALIAS void SERCOM0_2_Handler(void);
WEAK_ALIAS void SERCOM0_OTHER_Handler(void);
WEAK_ALIAS void SERCOM1_0_Handler(void);
WEAK_ALIAS void SERCOM1_1_Handler(void);
WEAK_ALIAS void SERCOM1_2_Handler(void);
WEAK_ALIAS void SERCOM1_OTHER_Handler(void);
WEAK_ALIAS void SERCOM2_0_Handler(void);
WEAK_ALIAS void SERCOM2_1_Handler(void);
WEAK_ALIAS void SERCOM2_2_Handler(void);
WEAK_ALIAS void SERCOM2_OTHER_Handler(void);
WEAK_ALIAS void SERCOM3_0_Handler(void);
WEAK_ALIAS void SERCOM3_1_Handler(void);
WEAK_ALIAS void SERCOM3_2_Handler(void);
WEAK_ALIAS void SERCOM3_OTHER_Handler(void);
WEAK_ALIAS void SERCOM4_0_Handler(void);
WEAK_ALIAS void SERCOM4_1_Handler(void);
WEAK_ALIAS void SERCOM4_2_Handler(void);
WEAK_ALIAS void SERCOM4_OTHER_Handler(void);
WEAK_ALIAS void SERCOM5_0_Handler(void);
WEAK_ALIAS void SERCOM5_1_Handler(void);
WEAK_ALIAS void SERCOM5_2_Handler(void);
WEAK_ALIAS void SERCOM5_OTHER_Handler(void);
WEAK_ALIAS void SERCOM6_0_Handler(void);
WEAK_ALIAS void SERCOM6_1_Handler(void);
WEAK_ALIAS void SERCOM6_2_Handler(void);
WEAK_ALIAS void SERCOM6_OTHER_Handler(void);
WEAK_ALIAS void SERCOM7_0_Handler(void);
WEAK_ALIAS void SERCOM7_1_Handler(void);
WEAK_ALIAS void SERCOM7_2_Handler(void);
WEAK_ALIAS void SERCOM7_OTHER_Handler(void);
WEAK_ALIAS void CAN0_Handler(void);
WEAK_ALIAS void CAN1_Handler(void);
WEAK_ALIAS void USB_OTHER_Handler(void);
WEAK_ALIAS void USB_SOF_HSOF_Handler(void);
WEAK_ALIAS void USB_TRCPT0_Handler(void);
WEAK_ALIAS void USB_TRCPT1_Handler(void);
WEAK_ALIAS void GMAC_Handler(void);
WEAK_ALIAS void TCC0_OTHER_Handler(void);
WEAK_ALIAS void TCC0_MC0_Handler(void);
WEAK_ALIAS void TCC0_MC1_Handler(void);
WEAK_ALIAS void TCC0_MC2_Handler(void);
WEAK_ALIAS void TCC0_MC3_Handler(void);
WEAK_ALIAS void TCC0_MC4_Handler(void);
WEAK_ALIAS void TCC0_MC5_Handler(void);
WEAK_ALIAS void TCC1_OTHER_Handler(void);
WEAK_ALIAS void TCC1_MC0_Handler(void);
WEAK_ALIAS void TCC1_MC1_Handler(void);
WEAK_ALIAS void TCC1_MC2_Handler(void);
WEAK_ALIAS void TCC1_MC3_Handler(void);
WEAK_ALIAS void TCC2_OTHER_Handler(void);
WEAK_ALIAS void TCC2_MC0_Handler(void);
WEAK_ALIAS void TCC2_MC1_Handler(void);
WEAK_ALIAS void TCC2_MC2_Handler(void);
WEAK_ALIAS void TCC3_OTHER_Handler(void);
WEAK_ALIAS void TCC3_MC0_Handler(void);
WEAK_ALIAS void TCC3_MC1_Handler(void);
WEAK_ALIAS void TCC4_OTHER_Handler(void);
WEAK_ALIAS void TCC4_MC0_Handler(void);
WEAK_ALIAS void TCC4_MC1_Handler(void);
WEAK_ALIAS void TC0_Handler(void);
WEAK_ALIAS void TC1_Handler(void);
WEAK_ALIAS void TC2_Handler(void);
WEAK_ALIAS void TC3_Handler(void);
WEAK_ALIAS void TC4_Handler(void);
WEAK_ALIAS void TC5_Handler(void);
WEAK_ALIAS void TC6_Handler(void);
WEAK_ALIAS void TC7_Handler(void);
WEAK_ALIAS void PDEC_OTHER_Handler(void);
WEAK_ALIAS void PDEC_MC0_Handler(void);
WEAK_ALIAS void PDEC_MC1_Handler(void);
WEAK_ALIAS void ADC0_OTHER_Handler(void);
WEAK_ALIAS void ADC0_RESRDY_Handler(void);
WEAK_ALIAS void ADC1_OTHER_Handler(void);
WEAK_ALIAS void ADC1_RESRDY_Handler(void);
WEAK_ALIAS void AC_Handler(void);
WEAK_ALIAS void DAC_OTHER_Handler(void);
WEAK_ALIAS void DAC_EMPTY_0_Handler(void);
WEAK_ALIAS void DAC_EMPTY_1_Handler(void);
WEAK_ALIAS void DAC_RESRDY_0_Handler(void);
WEAK_ALIAS void DAC_RESRDY_1_Handler(void);
WEAK_ALIAS void I2S_Handler(void);
WEAK_ALIAS void PCC_Handler(void);
WEAK_ALIAS void AES_Handler(void);
WEAK_ALIAS void TRNG_Handler(void);
WEAK_ALIAS void ICM_Handler(void);
WEAK_ALIAS void PUKCC_Handler(void);
WEAK_ALIAS void QSPI_Handler(void);
WEAK_ALIAS void SDHC0_Handler(void);
WEAK_ALIAS void SDHC1_Handler(void);
__attribute__((section(".vectors"))) void (*const tab[16 + 138])(void) = {
_estack,
Reset_Handler,
NMI_Handler,
HardFault_Handler,
MemoryManagement_Handler,
BusFault_Handler,
UsageFault_Handler,
NULL,
NULL,
NULL,
NULL,
SVCall_Handler,
DebugMonitor_Handler,
NULL,
PendSV_Handler,
SysTick_Handler,
PM_Handler, // 0 Power
MCLK_Handler, // 1 Main
OSCCTRL_XOSC0_Handler, // 2 Oscillators
OSCCTRL_XOSC1_Handler, // 3 Oscillators
OSCCTRL_DFLL_Handler, // 4 Oscillators
OSCCTRL_DPLL0_Handler, // 5 Oscillators
OSCCTRL_DPLL1_Handler, // 6 Oscillators
OSC32KCTRL_Handler, // 7 32kHz
SUPC_OTHER_Handler, // 8 Supply
SUPC_BODDET_Handler, // 9 Supply
WDT_Handler, // 10 Watchdog
RTC_Handler, // 11 Real-Time
EIC_EXTINT_0_Handler, // 12 External
EIC_EXTINT_1_Handler, // 13 External
EIC_EXTINT_2_Handler, // 14 External
EIC_EXTINT_3_Handler, // 15 External
EIC_EXTINT_4_Handler, // 16 External
EIC_EXTINT_5_Handler, // 17 External
EIC_EXTINT_6_Handler, // 18 External
EIC_EXTINT_7_Handler, // 19 External
EIC_EXTINT_8_Handler, // 20 External
EIC_EXTINT_9_Handler, // 21 External
EIC_EXTINT_10_Handler, // 22 External
EIC_EXTINT_11_Handler, // 23 External
EIC_EXTINT_12_Handler, // 24 External
EIC_EXTINT_13_Handler, // 25 External
EIC_EXTINT_14_Handler, // 26 External
EIC_EXTINT_15_Handler, // 27 External
FREQM_Handler, // 28 Frequency
NVMCTRL_0_Handler, // 29 Non-Volatile
NVMCTRL_1_Handler, // 30 Non-Volatile
DMAC_0_Handler, // 31 Direct
DMAC_1_Handler, // 32 Direct
DMAC_2_Handler, // 33 Direct
DMAC_3_Handler, // 34 Direct
DMAC_OTHER_Handler, // 35 Direct
EVSYS_0_Handler, // 36 Event
EVSYS_1_Handler, // 37 Event
EVSYS_2_Handler, // 38 Event
EVSYS_3_Handler, // 39 Event
EVSYS_OTHER_Handler, // 40 Event
PAC_Handler, // 41 Peripheral
0, // 42 Reserved
0, // 43 Reserved
0, // 44 Reserved
RAMECC_Handler, // 45 RAM
SERCOM0_0_Handler, // 46 Serial
SERCOM0_1_Handler, // 47 Serial
SERCOM0_2_Handler, // 48 Serial
SERCOM0_OTHER_Handler, // 49 Serial
SERCOM1_0_Handler, // 50 Serial
SERCOM1_1_Handler, // 51 Serial
SERCOM1_2_Handler, // 52 Serial
SERCOM1_OTHER_Handler, // 53 Serial
SERCOM2_0_Handler, // 54 Serial
SERCOM2_1_Handler, // 55 Serial
SERCOM2_2_Handler, // 56 Serial
SERCOM2_OTHER_Handler, // 57 Serial
SERCOM3_0_Handler, // 58 Serial
SERCOM3_1_Handler, // 59 Serial
SERCOM3_2_Handler, // 60 Serial
SERCOM3_OTHER_Handler, // 61 Serial
SERCOM4_0_Handler, // 62 Serial
SERCOM4_1_Handler, // 63 Serial
SERCOM4_2_Handler, // 64 Serial
SERCOM4_OTHER_Handler, // 65 Serial
SERCOM5_0_Handler, // 66 Serial
SERCOM5_1_Handler, // 67 Serial
SERCOM5_2_Handler, // 68 Serial
SERCOM5_OTHER_Handler, // 69 Serial
SERCOM6_0_Handler, // 70 Serial
SERCOM6_1_Handler, // 71 Serial
SERCOM6_2_Handler, // 72 Serial
SERCOM6_OTHER_Handler, // 73 Serial
SERCOM7_0_Handler, // 74 Serial
SERCOM7_1_Handler, // 75 Serial
SERCOM7_2_Handler, // 76 Serial
SERCOM7_OTHER_Handler, // 77 Serial
CAN0_Handler, // 78 Control
CAN1_Handler, // 79 Control
USB_OTHER_Handler, // 80 Universal
USB_SOF_HSOF_Handler, // 81 Universal
USB_TRCPT0_Handler, // 82 Universal
USB_TRCPT1_Handler, // 83 Universal
GMAC_Handler, // 84 Ethernet
TCC0_OTHER_Handler, // 85 Timer
TCC0_MC0_Handler, // 86 Timer
TCC0_MC1_Handler, // 87 Timer
TCC0_MC2_Handler, // 88 Timer
TCC0_MC3_Handler, // 89 Timer
TCC0_MC4_Handler, // 90 Timer
TCC0_MC5_Handler, // 91 Timer
TCC1_OTHER_Handler, // 92 Timer
TCC1_MC0_Handler, // 93 Timer
TCC1_MC1_Handler, // 94 Timer
TCC1_MC2_Handler, // 95 Timer
TCC1_MC3_Handler, // 96 Timer
TCC2_OTHER_Handler, // 97 Timer
TCC2_MC0_Handler, // 98 Timer
TCC2_MC1_Handler, // 99 Timer
TCC2_MC2_Handler, // 100 Timer
TCC3_OTHER_Handler, // 101 Timer
TCC3_MC0_Handler, // 102 Timer
TCC3_MC1_Handler, // 103 Timer
TCC4_OTHER_Handler, // 104 Timer
TCC4_MC0_Handler, // 105 Timer
TCC4_MC1_Handler, // 106 Timer
TC0_Handler, // 107 Basic
TC1_Handler, // 108 Basic
TC2_Handler, // 109 Basic
TC3_Handler, // 110 Basic
TC4_Handler, // 111 Basic
TC5_Handler, // 112 Basic
TC6_Handler, // 113 Basic
TC7_Handler, // 114 Basic
PDEC_OTHER_Handler, // 115 Quadrature
PDEC_MC0_Handler, // 116 Quadrature
PDEC_MC1_Handler, // 117 Quadrature
ADC0_OTHER_Handler, // 118 Analog
ADC0_RESRDY_Handler, // 119 Analog
ADC1_OTHER_Handler, // 120 Analog
ADC1_RESRDY_Handler, // 121 Analog
AC_Handler, // 122 Analog
DAC_OTHER_Handler, // 123 Digital-to-Analog
DAC_EMPTY_0_Handler, // 124 Digital-to-Analog
DAC_EMPTY_1_Handler, // 125 Digital-to-Analog
DAC_RESRDY_0_Handler, // 126 Digital-to-Analog
DAC_RESRDY_1_Handler, // 127 Digital-to-Analog
I2S_Handler, // 128 Inter-IC
PCC_Handler, // 129 Parallel
AES_Handler, // 130 Advanced
TRNG_Handler, // 131 True
ICM_Handler, // 132 Integrity
PUKCC_Handler, // 133 PUblic-Key
QSPI_Handler, // 134 Quad
SDHC0_Handler, // 135 SD/MMC
SDHC1_Handler // 136 SD/MMC
};
__attribute__((naked, noreturn)) void Reset_Handler(void) {
// Clear BSS section, and copy data section from flash to RAM
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++;
SCB->VTOR = (uint32_t) &tab;
SystemInit();
// Call main()
extern void main(void);
main();
for (;;) (void) 0; // Infinite loop
}
void Default_Handler(void) {
for (;;) (void) 0;
}
@@ -0,0 +1,89 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include <sys/stat.h>
#include "hal.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(UART_DEBUG, 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;
}
void _init(void) {
}
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+1 -1
View File
@@ -47,7 +47,7 @@ static void fn2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
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;
c->is_draining = 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) {
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
-2
View File
@@ -102,9 +102,7 @@ int main(int argc, char *argv[]) {
// Start infinite event loop
MG_INFO(("Mongoose version : v%s", MG_VERSION));
MG_INFO(("Listening on : %s", HTTP_URL));
#if MG_ENABLE_MBEDTLS || MG_ENABLE_OPENSSL
MG_INFO(("Listening on : %s", HTTPS_URL));
#endif
web_init(&mgr);
while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop
+2 -2
View File
@@ -1,11 +1,11 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
#CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+8 -7
View File
@@ -29,8 +29,8 @@ static const char *s_url =
// 3. From the dialog box that appears, download:
// xxx-certificate.pem.crt as cert.pem to the example directory
// xxx-private.pem.key as key.pem to the example directory
static const char *s_cert = "cert.pem";
static const char *s_key = "key.pem";
// static const char *s_cert = "cert.pem";
// static const char *s_key = "key.pem";
static const char *s_rx_topic = "d/rx";
static const char *s_tx_topic = "d/tx";
@@ -41,14 +41,15 @@ static int s_qos = 1;
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_CONNECT) {
if (mg_url_is_ssl(s_url)) {
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = mg_url_host(s_url)};
mg_tls_init(c, &opts);
}
} else if (ev == MG_EV_ERROR) {
// On error, log error message
MG_ERROR(("%p %s", c->fd, (char *) ev_data));
} else if (ev == MG_EV_CONNECT) {
// Set up 2-way TLS that is required by AWS IoT
struct mg_tls_opts opts = {
.ca = "ca.pem", .cert = s_cert, .certkey = s_key};
mg_tls_init(c, &opts);
} else if (ev == MG_EV_MQTT_OPEN) {
// MQTT connect is successful
struct mg_str topic = mg_str(s_rx_topic);
+1
View File
@@ -0,0 +1 @@
../http-client/packed_fs.c
+2 -2
View File
@@ -1,11 +1,11 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
#CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+9 -7
View File
@@ -20,21 +20,23 @@ static struct mg_connection *s_conn; // Client connection
// Handle interrupts, like Ctrl-C
static int s_signo;
static void signal_handler(int signo) { s_signo = signo; }
static void signal_handler(int signo) {
s_signo = signo;
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_OPEN) {
MG_INFO(("%lu CREATED", c->id));
// c->is_hexdumping = 1;
} else if (ev == MG_EV_CONNECT) {
if (mg_url_is_ssl(s_url)) {
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = mg_url_host(s_url)};
mg_tls_init(c, &opts);
}
} else if (ev == MG_EV_ERROR) {
// On error, log error message
MG_ERROR(("%lu ERROR %s", c->id, (char *) ev_data));
} else if (ev == MG_EV_CONNECT) {
// If target URL is SSL/TLS, command client connection to use TLS
if (mg_url_is_ssl(s_url)) {
struct mg_tls_opts opts = {.ca = "ca.pem"};
mg_tls_init(c, &opts);
}
} else if (ev == MG_EV_MQTT_OPEN) {
// MQTT connect is successful
struct mg_str subt = mg_str(s_sub_topic);
+1
View File
@@ -0,0 +1 @@
../http-client/packed_fs.c
+2 -2
View File
@@ -1,11 +1,11 @@
PROG ?= example # Program we are building
DELETE = rm -rf # Command to remove files
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c # Source code files
SOURCES = main.c mongoose.c packed_fs.c # Source code files, packed_fs.c contains ca.pem, which contains CA certs for TLS
CFLAGS = -W -Wall -Wextra -g -I. # Build options
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
#CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG ?= example.exe # Use .exe suffix for the binary
-1
View File
@@ -1 +0,0 @@
../../test/data/ca.pem
+13 -14
View File
@@ -9,15 +9,15 @@
//
// To enable SSL/TLS, see https://mongoose.ws/tutorials/tls/#how-to-build
static const char *s_url =
#if defined(MG_ENABLE_MBEDTLS) || defined(MG_ENABLE_OPENSSL)
"wss://broker.hivemq.com:8884/mqtt";
#else
"ws://broker.hivemq.com:8000/mqtt";
#endif
#include "mongoose.h"
static const char *s_url =
#if MG_TLS
"wss://broker.hivemq.com:8884/mqtt";
#else
"ws://broker.hivemq.com:8000/mqtt";
#endif
static const char *s_topic = "mg/test";
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
@@ -25,17 +25,16 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
// On error, log error message
MG_ERROR(("%p %s", c->fd, (char *) ev_data));
} else if (ev == MG_EV_CONNECT) {
// If target URL is SSL/TLS, command client connection to use TLS
if (mg_url_is_ssl(s_url)) {
struct mg_tls_opts opts = {.ca = "ca.pem"};
struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"),
.name = mg_url_host(s_url)};
mg_tls_init(c, &opts);
}
} else if (ev == MG_EV_WS_OPEN) {
// WS connection established. Perform MQTT login
MG_INFO(("Connected to WS. Logging in to MQTT..."));
struct mg_mqtt_opts opts = {.qos = 1,
.topic = mg_str(s_topic),
.message = mg_str("goodbye")};
struct mg_mqtt_opts opts = {
.qos = 1, .topic = mg_str(s_topic), .message = mg_str("goodbye")};
size_t len = c->send.len;
mg_mqtt_login(c, &opts);
mg_ws_wrap(c, c->send.len - len, WEBSOCKET_OP_BINARY);
@@ -72,7 +71,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
len = mg_ws_wrap(c, c->send.len - len, WEBSOCKET_OP_BINARY);
} else {
MG_ERROR(("%lu MQTT auth failed, code %d", c->id, mm.ack));
c->is_closing = 1;
c->is_draining = 1;
}
break;
case MQTT_CMD_PUBLISH: {
@@ -80,7 +79,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
mm.topic.ptr, (int) mm.data.len, mm.data.ptr));
MG_INFO(("RECEIVED %.*s <- %.*s", (int) mm.data.len, mm.data.ptr,
(int) mm.topic.len, mm.topic.ptr));
c->is_closing = 1;
c->is_draining = 1;
break;
}
}
+1
View File
@@ -0,0 +1 @@
../http-client/packed_fs.c
@@ -0,0 +1,73 @@
CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include -Icmsis_mcu/devices/MIMXRT1021 #-DCPU_MIMXRT1021DAG5A
CFLAGS += -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16
LDFLAGS ?= -Tlink_ram.ld -nostdlib -nostartfiles --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = main.c syscalls.c sysinit.c
SOURCES += cmsis_mcu/devices/MIMXRT1021/gcc/startup_MIMXRT1021.S # NXP startup file. Compiler-dependent!
CFLAGS += -D__ATOLLIC__ -D__STARTUP_CLEAR_BSS # Make startup code work as expected
# Mongoose-specific. See https://mongoose.ws/documentation/#build-options
SOURCES += mongoose.c
CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1
CFLAGS += -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_DRIVER_IMXRT1020=1
CFLAGS += $(CFLAGS_EXTRA)
# Example specific build options. See README.md
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F /S
else
RM = rm -rf
endif
all build example: firmware.bin
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
firmware.elf: cmsis_core cmsis_mcu $(SOURCES) hal.h link_ram.ld Makefile
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
arm-none-eabi-size $@
flash: firmware.bin
st-flash --reset write $< 0x8000000
cmsis_core: # ARM CMSIS core headers
git clone -q --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
cmsis_mcu:
curl -sL https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1021_DFP.17.0.0.pack -o $@.zip
mkdir $@ && cd $@ && unzip -q ../$@.zip
mbedtls: # mbedTLS library
git clone --depth 1 -b v2.28.2 https://github.com/mbed-tls/mbedtls $@
ifeq ($(TLS), mbedtls)
CFLAGS += -DMG_TLS=MG_TLS_MBED -Wno-conversion -Imbedtls/include
CFLAGS += -DMBEDTLS_CONFIG_FILE=\"mbedtls_config.h\" mbedtls/library/*.c
firmware.elf: mbedtls
endif
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/4
update: firmware.bin
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$<
curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"init"}'
curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"wm,e000edf0,a05f0003 wm,e000edfc,1 wm,e000ed0c,5fa0004"}'
curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"init"}'
PC=`curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"rm,4"}' | jq -r .resp[5:]` && \
SP=`curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"rm,0"}' | jq -r .resp[5:]` && \
REQ="wm,e000ed08,0 wr,d,$$SP wr,f,$$PC" && \
curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"'"$$REQ"'"}'
curl -su :$(VCON_API_KEY) $(DEVICE_URL)/rpc/swd.exec -d '{"req":"wm,e000edf0,a05f0001"}'
test update: CFLAGS += -DUART_DEBUG=LPUART2
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
clean:
$(RM) firmware.* *.su cmsis_core cmsis_mcu mbedtls *.zip
@@ -0,0 +1,303 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
// https://www.nxp.com/webapp/Download?colCode=IMXRT1020RM
// https://cache.nxp.com/secured/assets/documents/en/user-guide/MIMXRT1020EVKHUG.pdf
#pragma once
#include "MIMXRT1021.h"
#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) - '0') << 8) | (num))
#define PINNO(pin) (pin & 255)
#define PINBANK(pin) (pin >> 8)
// Use LED for blinking, GPIO_AD_B0_05. GPIO1.5 (schematics)
#define LED PIN('1', 5)
#ifndef UART_DEBUG
#define UART_DEBUG LPUART1
#endif
// No settable constants, see sysinit.c
#define SYS_FREQUENCY 500000000UL
static inline void spin(volatile uint32_t count) {
while (count--) (void) 0;
}
enum { CLOCK_OFF = 0U, CLOCK_ON_RUN = 1U, CLOCK_ON_RUN_WAIT = 3U };
static inline void clock_periph(uint32_t index, uint32_t shift, uint32_t val) {
volatile uint32_t *r = &CCM->CCGR0;
SETBITS(r[index], 3UL << shift, val << shift);
}
// which peripheral feeds the pin
static inline void gpio_mux_config(uint16_t index, uint8_t af) {
IOMUXC->SW_MUX_CTL_PAD[index] = af;
}
// which pin feeds the peripheral (2nd stage)
static inline void periph_mux_config(uint16_t index, uint8_t in) {
IOMUXC->SELECT_INPUT[index] = in;
}
enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT };
enum { GPIO_OTYPE_PUSH_PULL, GPIO_OTYPE_OPEN_DRAIN };
enum { GPIO_SPEED_LOW, GPIO_SPEED_MEDIUM, GPIO_SPEED_MEDIUM_, GPIO_SPEED_HIGH };
enum { GPIO_PULL_NONE, GPIO_PULL_DOWN, GPIO_PULL_UP };
static inline GPIO_Type *gpio_bank(uint16_t pin) {
static const GPIO_Type *g[] = {NULL, GPIO1, GPIO2, GPIO3, NULL, GPIO5};
return (GPIO_Type *) g[PINBANK(pin)];
}
// pin driver/pull-up/down configuration (ignore "keeper")
static inline void gpio_pad_config(uint16_t index, uint8_t type, uint8_t speed,
uint8_t pull) {
bool dopull = pull > 0;
if (dopull) --pull;
IOMUXC->SW_PAD_CTL_PAD[index] =
IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_ODE(type) |
IOMUXC_SW_PAD_CTL_PAD_SRE(speed >= GPIO_SPEED_HIGH) |
IOMUXC_SW_PAD_CTL_PAD_PUE(1) | IOMUXC_SW_PAD_CTL_PAD_PKE(dopull) |
IOMUXC_SW_PAD_CTL_PAD_PUS(pull) | IOMUXC_SW_PAD_CTL_PAD_DSE(7);
}
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
uint8_t speed, uint8_t pull) {
GPIO_Type *gpio = gpio_bank(pin);
uint8_t bit = (uint8_t) PINNO(pin);
uint32_t mask = (uint32_t) BIT(PINNO(pin));
clock_periph(4, CCM_CCGR4_CG1_SHIFT, CLOCK_ON_RUN_WAIT); // iomuxc_ipg_clk_s
switch (PINBANK(pin)) {
case 1:
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_00 + bit, 5);
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_00 + bit, type, speed,
pull);
clock_periph(1, CCM_CCGR1_CG13_SHIFT, CLOCK_ON_RUN_WAIT);
break;
case 2:
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_00 + bit, 5);
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_00 + bit, type, speed,
pull);
clock_periph(0, CCM_CCGR0_CG15_SHIFT, CLOCK_ON_RUN_WAIT);
break;
case 3:
gpio_mux_config(bit < 13
? kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32 + bit
: kIOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00 + bit - 13,
5);
gpio_pad_config(bit < 13
? kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_32 + bit
: kIOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_00 + bit - 13,
type, speed, pull);
clock_periph(2, CCM_CCGR2_CG13_SHIFT, CLOCK_ON_RUN_WAIT);
break;
case 5:
// TODO(): support sw_mux
clock_periph(1, CCM_CCGR1_CG15_SHIFT, CLOCK_ON_RUN_WAIT);
break;
default:
break;
}
gpio->IMR &= ~mask;
if (mode == GPIO_MODE_INPUT) {
gpio->GDIR &= ~mask;
} else {
gpio->GDIR |= mask;
}
}
static inline void gpio_input(uint16_t pin) {
gpio_init(pin, GPIO_MODE_INPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_MEDIUM,
GPIO_PULL_NONE);
}
static inline void gpio_output(uint16_t pin) {
gpio_init(pin, GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_MEDIUM,
GPIO_PULL_NONE);
}
static inline bool gpio_read(uint16_t pin) {
GPIO_Type *gpio = gpio_bank(pin);
uint32_t mask = (uint32_t) BIT(PINNO(pin));
return gpio->DR & mask;
}
static inline void gpio_write(uint16_t pin, bool value) {
GPIO_Type *gpio = gpio_bank(pin);
uint32_t mask = (uint32_t) BIT(PINNO(pin));
if (value) {
gpio->DR |= mask;
} else {
gpio->DR &= ~mask;
}
}
static inline void gpio_toggle(uint16_t pin) {
gpio_write(pin, !gpio_read(pin));
}
// 14.5 Table 14-4: uart_clk_root
// see sysinit.c for clocks, (14.7.9: defaults to PLL3/6/1 = 80MHz)
static inline void uart_init(LPUART_Type *uart, unsigned long baud) {
uint8_t af = 2; // Alternate function
uint16_t mr = 0, pr = 0, mt = 0, pt = 0; // pins
uint32_t freq = 80000000; // uart_clk_root frequency
if (uart == LPUART1)
mt = kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_06,
pt = kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_06,
mr = kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_07,
pr = kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_07;
if (uart == LPUART2)
mt = kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08,
pt = kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_08,
mr = kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09,
pr = kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09;
if (uart == LPUART1) clock_periph(5, CCM_CCGR5_CG12_SHIFT, CLOCK_ON_RUN_WAIT);
if (uart == LPUART2) clock_periph(0, CCM_CCGR0_CG14_SHIFT, CLOCK_ON_RUN_WAIT);
clock_periph(4, CCM_CCGR4_CG1_SHIFT, CLOCK_ON_RUN_WAIT); // iomuxc_ipg_clk_s
gpio_mux_config(mt, af);
gpio_pad_config(pt, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_UP);
gpio_mux_config(mr, af);
gpio_pad_config(pr, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_UP);
uart->GLOBAL |= LPUART_GLOBAL_RST_MASK; // reset, CTRL = 0, defaults
uart->GLOBAL &= ~LPUART_GLOBAL_RST_MASK;
SETBITS(uart->BAUD,
LPUART_BAUD_OSR_MASK | LPUART_BAUD_SBR_MASK | LPUART_BAUD_SBNS_MASK,
LPUART_BAUD_OSR(16 - 1) |
LPUART_BAUD_SBR(freq / (16 * baud))); // Rx sample at 16x
SETBITS(uart->CTRL,
LPUART_CTRL_PE_MASK | LPUART_CTRL_M_MASK | LPUART_CTRL_ILT_MASK |
LPUART_CTRL_IDLECFG_MASK,
LPUART_CTRL_IDLECFG(1) | LPUART_CTRL_ILT(1) |
LPUART_BAUD_SBNS(0)); // no parity, idle 2 chars after 1 stop bit
uart->CTRL |= LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK;
}
static inline void uart_write_byte(LPUART_Type *uart, uint8_t byte) {
uart->DATA = byte;
while ((uart->STAT & LPUART_STAT_TDRE_MASK) == 0) spin(1);
}
static inline void uart_write_buf(LPUART_Type *uart, char *buf, size_t len) {
while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++);
}
static inline int uart_read_ready(LPUART_Type *uart) {
(void) uart;
return uart->STAT & LPUART_STAT_RDRF_MASK;
}
static inline uint8_t uart_read_byte(LPUART_Type *uart) {
return (uint8_t) (uart->DATA & 255);
}
static inline void rng_init(void) {
clock_periph(6, CCM_CCGR6_CG6_SHIFT, CLOCK_ON_RUN_WAIT); // trng_clk
SETBITS(TRNG->MCTL,
TRNG_MCTL_PRGM_MASK | TRNG_MCTL_ERR_MASK | TRNG_MCTL_RST_DEF_MASK,
TRNG_MCTL_PRGM(1) | TRNG_MCTL_ERR(1) |
TRNG_MCTL_RST_DEF(1)); // reset to default values
SETBITS(TRNG->MCTL, TRNG_MCTL_PRGM_MASK | TRNG_MCTL_ERR_MASK,
TRNG_MCTL_PRGM(0)); // set to run mode
(void) TRNG->ENT[TRNG_ENT_COUNT - 1]; // start new entropy generation
(void) TRNG->ENT[0]; // defect workaround
}
static inline uint32_t rng_read(void) {
static uint8_t idx = 0;
while ((TRNG->MCTL & TRNG_MCTL_ENT_VAL_MASK) == 0) (void) 0;
uint32_t data = TRNG->ENT[idx++]; // read data
idx %= TRNG_ENT_COUNT; // stay within array limits
if (idx == 0) // we've just read TRNG_ENT_COUNT - 1
(void) TRNG->ENT[0]; // defect workaround
return data;
}
// - PHY has no xtal, XI driven from ENET_REF_CLK1 (labeled as ENET_TX_CLK
// (GPIO_AD_B0_08)), generated by the MCU
// - PHY RST connected to GPIO1.4 (GPIO_AD_B0_04); INTRP/NAND_TREE connected to
// GPIO1.22 (GPIO_AD_B1_06)
// - 37.4 REF_CLK1 is RMII mode reference clock for Rx, Tx, and SMI; it is I/O
// - 11.4.2 IOMUXC_GPR_GPR1 bit 17: ENET_REF_CLK_DIR --> 1 ENET_REF_CLK is
// output driven by ref_enetpll0
// - 14.6.1.3.4 Ethernet PLL (PLL6)
static inline void ethernet_init(void) {
gpio_init(PIN('1', 4), GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_MEDIUM, GPIO_PULL_UP); // set GPIO1.4 as GPIO (PHY \RST)
gpio_write(PIN('1', 4), 0); // reset PHY
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_08,
4); // set for ENET_REF_CLK1
IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_08] |=
IOMUXC_SW_MUX_CTL_PAD_SION(1); // loop signal back from pin
periph_mux_config(kIOMUXC_ENET_RMII_SELECT_INPUT,
1); // drive peripheral from B0_08, so RMII clock is taken
// from ENET_REF_CLK1
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_08, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_09, 0); // set for RXDATA1
periph_mux_config(kIOMUXC_ENET_RX_DATA1_SELECT_INPUT,
1); // drive peripheral from B0_09
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_09, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_10, 0); // set for RXDATA0
periph_mux_config(kIOMUXC_ENET_RX_DATA0_SELECT_INPUT,
1); // drive peripheral from B0_10
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_10, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_11, 0); // set for CRS
periph_mux_config(kIOMUXC_ENET_RX_EN_SELECT_INPUT,
1); // drive peripheral from B0_11
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_11, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12, 0); // set for RXERR
periph_mux_config(kIOMUXC_ENET_RX_ERR_SELECT_INPUT,
1); // drive peripheral from B0_12
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_12, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13, 0); // set for TXEN
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_13, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_14, 0); // set for TXDATA0
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_14, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_15, 0); // set for TXDATA1
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_15, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_HIGH, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_40, 4); // set for MDIO
periph_mux_config(kIOMUXC_ENET_MDIO_SELECT_INPUT,
2); // drive peripheral from EMC_40
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_40, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_MEDIUM, GPIO_PULL_UP);
gpio_mux_config(kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_41, 4); // set for MDC
gpio_pad_config(kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_41, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_MEDIUM, GPIO_PULL_UP);
gpio_init(PIN('1', 22), GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL,
GPIO_SPEED_MEDIUM,
GPIO_PULL_UP); // set GPIO1.22 as GPIO (PHY INTRP/NAND_TREE)
gpio_write(PIN('1', 22), 1); // prevent NAND_TREE
// 14.8.9 Use 500MHz reference and generate 50MHz. This is done at sysinit.c,
// as we use this source to clock the core
spin(10000); // keep PHY RST low for a while
gpio_write(PIN('1', 4), 1); // deassert RST
gpio_init(PIN('1', 22), GPIO_MODE_INPUT, 0, GPIO_SPEED_MEDIUM,
GPIO_PULL_UP); // setup IRQ (pulled-up)(not used)
IOMUXC_GPR->GPR1 |=
IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR(1); // Set ENET_REF_CLK1 as output
clock_periph(1, CCM_CCGR1_CG5_SHIFT, CLOCK_ON_RUN_WAIT); // enet_ipg_clk
NVIC_EnableIRQ(ENET_IRQn); // Setup Ethernet IRQ handler
}
// Helper macro for MAC generation, byte reads not allowed
#define GENERATE_LOCALLY_ADMINISTERED_MAC() \
{ \
2, OCOTP->CFG0 & 255, (OCOTP->CFG0 >> 10) & 255, \
((OCOTP->CFG0 >> 19) ^ (OCOTP->CFG1 >> 19)) & 255, \
(OCOTP->CFG1 >> 10) & 255, OCOTP->CFG1 & 255 \
}
@@ -0,0 +1,22 @@
ENTRY(Reset_Handler);
MEMORY {
flash_cfg(rx) : ORIGIN = 0x60000000, LENGTH = 4k
flash_ivt(rx) : ORIGIN = 0x60001000, LENGTH = 4k
flash_irq(rx) : ORIGIN = 0x60002000, LENGTH = 1k
flash_code(rx) : ORIGIN = 0x60002400, LENGTH = 8183k
ram0(rx) : ORIGIN = 0x00000000, LENGTH = 64k
ram1(rw) : ORIGIN = 0x20000000, LENGTH = 64k
ram2(rw) : ORIGIN = 0x20200000, LENGTH = 128k
}
__StackTop = ORIGIN(ram2) + LENGTH(ram2);
SECTIONS {
.cfg : { __FLASH_BASE = .; KEEP(* (.cfg)) } > flash_cfg
.ivt : { KEEP(*(.ivt)) } > flash_ivt
.irq : { KEEP(*(.isr_vector)) } > flash_irq
.text : { *(.text* .text.*) *(.rodata*) __etext = .; } > flash_code
.data : { __data_start__ = .; *(.data SORT(.data.*)) __data_end__ = .; } > ram1 AT > flash_code
.bss : { __bss_start__ = .; *(.bss SORT(.bss.*) COMMON) __bss_end__ = .; } > ram1
_end = .;
}
@@ -0,0 +1 @@
cmsis_mcu/devices/MIMXRT1021/gcc/MIMXRT1021xxxxx_ram.ld
@@ -0,0 +1,16 @@
ENTRY(Reset_Handler);
MEMORY {
itcram(rx) : ORIGIN = 0x00000000, LENGTH = 64k
dtcram(rw) : ORIGIN = 0x20000000, LENGTH = 64k
ocram(rw) : ORIGIN = 0x20200000, LENGTH = 128k /* This is cached */
}
__StackTop = ORIGIN(dtcram) + LENGTH(dtcram);
SECTIONS {
.irq : { KEEP(*(.isr_vector)) } > itcram
.text : { *(.text* .text.*) *(.rodata*) ; } > itcram
.data : { __data_start__ = .; *(.data SORT(.data.*)) __data_end__ = .; } > dtcram AT > itcram
__etext = LOADADDR(.data);
.bss : { __bss_start__ = .; *(.bss SORT(.bss.*) COMMON) __bss_end__ = .; } > dtcram
_end = .;
}
@@ -0,0 +1,93 @@
// Copyright (c) 2022-2023 Cesanta Software Limited
// All rights reserved
#include "hal.h"
#include "mongoose.h"
#include "net.h"
#define BLINK_PERIOD_MS 1000 // LED blinking period in millis
static volatile uint64_t s_ticks; // Milliseconds since boot
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
s_ticks++;
}
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
return s_ticks; // Return number of milliseconds since boot
}
void mg_random(void *buf, size_t len) { // Use on-board RNG
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
uint32_t r = rng_read();
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
}
}
static void timer_fn(void *arg) {
gpio_toggle(LED); // Blink LED
struct mg_tcpip_if *ifp = arg; // And show
const char *names[] = {"down", "up", "req", "ready"}; // network stats
MG_INFO(("Ethernet: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
ifp->ndrop, ifp->nerr));
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) 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")) { // Request to /api/hello
mg_http_reply(c, 200, "", "{%m:%u,%m:%u,%m:%u,%m:%u,%m:%u}\n",
MG_ESC("eth"), ifp->state, MG_ESC("frames_received"),
ifp->nrecv, MG_ESC("frames_sent"), ifp->nsent,
MG_ESC("frames_dropped"), ifp->ndrop,
MG_ESC("interface_errors"), ifp->nerr);
} else if (mg_http_match_uri(hm, "/")) { // Index page
mg_http_reply(
c, 200, "", "%s",
"<html><head><link rel='icon' href='data:;base64,='></head><body>"
"<h1>Welcome to Mongoose</h1>"
"See <a href=/api/hello>/api/hello</a> for REST example"
"</body></html>");
} else { // All other URIs
mg_http_reply(c, 404, "", "Not Found\n");
}
}
}
int main(void) {
gpio_output(LED); // Setup blue LED
uart_init(UART_DEBUG, 115200); // Initialise debug printf
ethernet_init(); // Initialise ethernet pins
MG_INFO(("Starting, CPU freq %g MHz", (double) SystemCoreClock / 1000000));
struct mg_mgr mgr; // Initialise
mg_mgr_init(&mgr); // Mongoose event manager
mg_log_set(MG_LL_DEBUG); // Set log level
// Initialise Mongoose network stack
struct mg_tcpip_driver_imxrt1020_data driver_data = {.mdc_cr = 24};
struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC(),
// Uncomment below for static configuration:
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
// .mask = mg_htonl(MG_U32(255, 255, 255, 0)),
// .gw = mg_htonl(MG_U32(192, 168, 0, 1)),
.driver = &mg_tcpip_driver_imxrt1020,
.driver_data = &driver_data};
mg_tcpip_init(&mgr, &mif);
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif);
MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac));
while (mif.state != MG_TCPIP_STATE_READY) {
mg_mgr_poll(&mgr, 0);
}
MG_INFO(("Initialising application..."));
mg_http_listen(&mgr, "http://0.0.0.0:80", fn, &mif);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -0,0 +1,98 @@
#include <sys/stat.h>
#include "hal.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;
unsigned char x = 0, *heap_end = (unsigned char *)((size_t) &x - 512);
(void) x;
if (heap == NULL) heap = (unsigned char *) &_end;
prev_heap = heap;
if (heap + incr > heap_end) return (void *) -1;
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(UART_DEBUG, 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;
}
void _init(void) {}
extern uint64_t mg_now(void);
int _gettimeofday(struct timeval *tv, void *tz) {
uint64_t now = mg_now();
(void) tz;
tv->tv_sec = (time_t) (now / 1000);
tv->tv_usec = (unsigned long) ((now % 1000) * 1000);
return 0;
}
@@ -0,0 +1,106 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
//
// This file contains essentials required by the CMSIS:
// uint32_t SystemCoreClock - holds the system core clock value
// SystemInit() - initialises the system, e.g. sets up clocks
#include "hal.h"
uint32_t SystemCoreClock = SYS_FREQUENCY;
// - 14.4, Figure 14-2: clock tree
// - 14.7.4: ARM_PODF defaults to /1
// - 14.7.5: AHB_PODF defaults to /1; PERIPH_CLK_SEL defaults to derive clock
// from pre_periph_clk_sel
// - 14.7.6: PRE_PERIPH_CLK_SEL defaults to derive clock from PLL2 PFD3.
// - (For 528MHz operation, we need to set it to derive clock from PLL2, but
// this chip max is 500 MHz).
// - 14.6.1.3.1 System PLL (PLL2); 13.3.2.2 PLLs; 14.6.1.4 Phase Fractional
// Dividers (PFD)
// - 14.8.2: PLL2 is powered off and bypassed to 24MHz
// - 14.8.11: PFD defaults to 18/16 but Figure 14-2 shows half the value
// ("divider")
// - For 500MHz operation, we need to set PRE_PERIPH_CLK_SEL to derive clock
// from divided PLL6
// - 14.8.9: configure PLL6 to generate a 500MHz clock
// - Datasheet 4.1.3: System frequency/Bus frequency max 500/125MHz respectively
// (AHB/IPG)
// - MCUXpresso: IPG_CLK_ROOT <= 125MHz; PERCLK_CLK_ROOT <= 62.5MHz
// - Datasheet 4.8.4.1.1/2: the processor clock frequency must exceed twice the
// ENET_RX_CLK/ENET_TX_CLK frequency.
// - Datasheet 4.8.4.2: no details for RMII (above is for MII), assumed 50MHz
// min processor clock
// - Datasheet 4.1.3, Table 11: "Overdrive" run mode requires 1.25V core voltage
// minimum
void SystemInit(void) { // Called automatically by startup code (ints masked)
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
asm("DSB");
asm("ISB");
// 53.4.2: Disable watchdog after reset (unlocked)
RTWDOG->CS &= ~RTWDOG_CS_EN_MASK;
RTWDOG->TOVAL = 0xFFFF;
while (RTWDOG->CS & RTWDOG_CS_ULK_MASK) spin(1); // wait for lock
while ((RTWDOG->CS & RTWDOG_CS_RCS_MASK) == 0)
spin(1); // wait for new config
// Set VDD_SOC to 1.25V
SETBITS(DCDC->REG3, DCDC_REG3_TRG_MASK, DCDC_REG3_TRG(0x12));
while ((DCDC->REG0 & DCDC_REG0_STS_DC_OK_MASK) == 0)
spin(1); // Wait for DCDC_STS_DC_OK
// 14.8.9 Init 500MHz reference, clock the M7 core with it, generate 50MHz for
// ENET and RMII.
SETBITS(CCM_ANALOG->PLL_ENET, CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK,
CCM_ANALOG_PLL_ENET_BYPASS_MASK |
CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC(0)); // bypass to 24MHz osc
SETBITS(
CCM_ANALOG->PLL_ENET,
CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK | CCM_ANALOG_PLL_ENET_POWERDOWN_MASK,
CCM_ANALOG_PLL_ENET_DIV_SELECT(1) | CCM_ANALOG_PLL_ENET_ENABLE_MASK |
CCM_ANALOG_PLL_ENET_ENET_500M_REF_EN_MASK); // setup PLL
while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0)
spin(1); // wait until it is stable
CCM_ANALOG->PLL_ENET &=
~CCM_ANALOG_PLL_ENET_BYPASS_MASK; // Disable Bypass (switch to PLL)
SETBITS(CCM->CBCDR, CCM_CBCDR_IPG_PODF_MASK,
CCM_CBCDR_IPG_PODF(3)); // Set IPG divider /4 (125MHz)
SETBITS(CCM->CSCMR1, CCM_CSCMR1_PERCLK_PODF_MASK,
CCM_CSCMR1_PERCLK_PODF(1)); // Set PERCLK divider /2 (62.5MHz)
SETBITS(CCM->CBCMR, CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK,
CCM_CBCMR_PRE_PERIPH_CLK_SEL(3)); // run from 500MHz clock
// 14.5 Table 14-4: uart_clk_root
// 14.4: uart_clk_root = PLL3/6 or OSC; CCM_CSCDR1 (14.7.9) defaults to
// PLL3/6/1
CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_POWER_MASK; // Power PLL on
while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0)
spin(1); // wait until it is stable
CCM_ANALOG->PLL_USB1 &=
~CCM_ANALOG_PLL_USB1_BYPASS_MASK; // Disable Bypass (switch to PLL)
rng_init(); // Initialise random number generator
// NXP startup code calls SystemInit BEFORE initializing RAM...
SysTick_Config(SYS_FREQUENCY / 1000); // Sys tick every 1ms
}
#if 0
__attribute__((section(".cfg"), used)) uint32_t __cfg[] = {0x1234abcd};
extern uint32_t __isr_vector[];
extern uint32_t __ivt_boot_data[];
__attribute__((section(".ivt"), used)) uint32_t __ivt[8] = {
0x412000d1, // header: 41 - version, 2000 size, d1 tag
(uint32_t) __isr_vector, // entry
0, // reserved
0, // dcd
(uint32_t) __ivt_boot_data, // boot data
(uint32_t) __ivt, // this is us - ivt absolute address
0, // csf absolute address
0, // reserved for HAB
};
__attribute__((section(".ivt"), used)) uint32_t __ivt_boot_data[] = {
0, // boot start location
64 * 1024, // size
0, // Plugin flag
0Xffffffff // empty - extra data word
};
#endif
@@ -0,0 +1 @@
cmsis_mcu/devices/MIMXRT1021/system_MIMXRT1021.c
Loaded 100 of 1275 files, more files were not shown because too many files have changed in this diff. Show more