mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
359060a151 | ||
|
|
af1aff7fbb | ||
|
|
517ef216c1 | ||
|
|
734c13cdf5 | ||
|
|
1bf3ad2426 | ||
|
|
884b9a4813 | ||
|
|
7153690016 | ||
|
|
f00b3a2b3a | ||
|
|
c2b5e4f3b8 | ||
|
|
bc15e9ce9a | ||
|
|
70dc6d8dc9 | ||
|
|
10b11b03a8 | ||
|
|
cb602f178c | ||
|
|
464113c5ae | ||
|
|
c34f6c54e7 | ||
|
|
8fb58ebbca | ||
|
|
dce60c6dbb | ||
|
|
f668d08804 | ||
|
|
c41a22195c | ||
|
|
900c05213b | ||
|
|
c5850e4b05 | ||
|
|
ff4649fe42 | ||
|
|
1a38e91042 | ||
|
|
b6196371bb | ||
|
|
d5beb7ba3f | ||
|
|
19acf23c49 | ||
|
|
5cd3291fec | ||
|
|
b3e0f780c3 | ||
|
|
2bdbfc27f6 | ||
|
|
3fc61a3edc | ||
|
|
12339bbf4c | ||
|
|
1fb9f922b0 | ||
|
|
b93bc02ab0 | ||
|
|
747e393a54 | ||
|
|
4e8660a21f | ||
|
|
3fe77fa9a6 | ||
|
|
b4fbaf7c13 | ||
|
|
9884241df8 | ||
|
|
63d7a4fa45 | ||
|
|
8f4b6c41a2 | ||
|
|
4493d65ec9 | ||
|
|
e5910da300 | ||
|
|
c277a1d878 | ||
|
|
7820ad3a59 | ||
|
|
23533b83a4 | ||
|
|
ab650ec5c9 | ||
|
|
8f36597048 | ||
|
|
d0213ee90a | ||
|
|
1e9fabe1ca | ||
|
|
148d3f0562 | ||
|
|
c3057df3f5 | ||
|
|
0b2e474d52 | ||
|
|
95a36b1759 | ||
|
|
86ffa3a3ea | ||
|
|
69e2b2985d | ||
|
|
c431904b56 | ||
|
|
c2a10601b9 | ||
|
|
e9a8e5468d | ||
|
|
22e602debb | ||
|
|
455cec67a5 | ||
|
|
e2dfac946d | ||
|
|
c198d2e5f1 | ||
|
|
9a70abef24 | ||
|
|
53e1c469a2 | ||
|
|
139c2061a8 | ||
|
|
15b361fbac | ||
|
|
3130e59244 | ||
|
|
93286836f9 | ||
|
|
91b57aa9a8 | ||
|
|
220231e647 | ||
|
|
c438bb0bc5 | ||
|
|
95afa323c0 | ||
|
|
bc56353a79 | ||
|
|
1ffccdb7b2 | ||
|
|
e79fe4b8f0 | ||
|
|
aaf1fc3a4a | ||
|
|
8b42353039 | ||
|
|
05c687e251 | ||
|
|
492b8f6950 | ||
|
|
8ccee82059 | ||
|
|
b99a94a652 | ||
|
|
41e5d7e471 | ||
|
|
1adea37c45 | ||
|
|
98f6c8aa4f | ||
|
|
341ae53e85 | ||
|
|
291fc024cd | ||
|
|
f63d833a33 | ||
|
|
ab035901f8 | ||
|
|
20f54059ad | ||
|
|
563c31303e | ||
|
|
421e099f2b | ||
|
|
955d4a3129 | ||
|
|
b84981ad03 | ||
|
|
777b8e94e2 | ||
|
|
6df642623a | ||
|
|
0a3e186f11 | ||
|
|
c2d83a9db0 | ||
|
|
f33d3a4e02 | ||
|
|
86b8a56b05 | ||
|
|
ac6ec15aed | ||
|
|
31632c6361 | ||
|
|
98c99279c3 | ||
|
|
cdb8d7b692 | ||
|
|
93ac3e19f0 | ||
|
|
6a51af9efe | ||
|
|
9d73b3470b | ||
|
|
1c8449cea6 | ||
|
|
3bbbd41196 | ||
|
|
339bbee0df | ||
|
|
9ba6eb716d | ||
|
|
d949c19c7e | ||
|
|
1299d6118f | ||
|
|
244ff92e78 | ||
|
|
53f34dea04 | ||
|
|
1f5c3fac31 | ||
|
|
7014258c8d | ||
|
|
1614e7ba8d | ||
|
|
43b5a4e735 | ||
|
|
43191db63e | ||
|
|
e89be2e944 | ||
|
|
c2fbff6d0e | ||
|
|
b8eca17c55 | ||
|
|
4650e491df | ||
|
|
3e33e57707 | ||
|
|
c80f4c5313 | ||
|
|
132ecbec2f | ||
|
|
0a90cab44a | ||
|
|
d16dbc197f | ||
|
|
127f27e375 | ||
|
|
6523cc4da0 | ||
|
|
2516da1c89 | ||
|
|
0ae2b82b60 | ||
|
|
dab526936f | ||
|
|
780077d118 | ||
|
|
ad8f1d88d4 | ||
|
|
a3c4a48ef7 | ||
|
|
84a11fe3b1 |
No files matched your search
@@ -1,8 +0,0 @@
|
|||||||
People who have agreed to the
|
|
||||||
[Cesanta CLA](https://docs.cesanta.com/contributors_la.shtml)
|
|
||||||
can make contributions. Note that the CLA isn't a copyright
|
|
||||||
_assigment_ but rather a copyright _license_.
|
|
||||||
You retain the copyright on your contributions.
|
|
||||||
|
|
||||||
We follow the Google C/C++ style guide: https://google.github.io/styleguide/cppguide.html
|
|
||||||
We'd appreciate if your contribution follows the same style guide.
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||||
Copyright (c) 2013-2016 Cesanta Software Limited
|
Copyright (c) 2013-2018 Cesanta Software Limited
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|
||||||
This software is dual-licensed: you can redistribute it and/or modify
|
This software is dual-licensed: you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operatin
|
|||||||
# Support
|
# Support
|
||||||
- [Study mongoose example code](https://github.com/cesanta/mongoose/tree/master/examples)
|
- [Study mongoose example code](https://github.com/cesanta/mongoose/tree/master/examples)
|
||||||
- [Read User Guide and API reference](https://cesanta.com/docs/overview/intro.html)
|
- [Read User Guide and API reference](https://cesanta.com/docs/overview/intro.html)
|
||||||
- [Support Forum - ask your technical questions here](https://forum.mongoose-os.com/categories/mongoose)
|
- [Support Forum - ask your technical questions here](https://community.mongoose-os.com/)
|
||||||
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
|
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
|
||||||
- [Check our latest releases](https://github.com/cesanta/mongoose/releases)
|
- [Check our latest releases](https://github.com/cesanta/mongoose/releases)
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ the functionality:
|
|||||||
# Contributions
|
# Contributions
|
||||||
|
|
||||||
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
|
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
|
||||||
and send GitHub pull request. You retain the copyright on your contributions.
|
and send GitHub pull request.
|
||||||
|
|
||||||
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
|
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
|
||||||
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
|
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
---
|
---
|
||||||
title: "Memory Buffers"
|
title: "mbuf.h"
|
||||||
symbol_kind: "intro"
|
symbol_kind: "intro"
|
||||||
decl_name: "mbuf.h"
|
decl_name: "mbuf.h"
|
||||||
items:
|
items:
|
||||||
- { name: mbuf_append.md }
|
- { name: mbuf_append.md }
|
||||||
|
- { name: mbuf_append_and_free.md }
|
||||||
|
- { name: mbuf_clear.md }
|
||||||
- { name: mbuf_free.md }
|
- { name: mbuf_free.md }
|
||||||
- { name: mbuf_init.md }
|
- { name: mbuf_init.md }
|
||||||
- { name: mbuf_insert.md }
|
- { name: mbuf_insert.md }
|
||||||
|
- { name: mbuf_move.md }
|
||||||
- { name: mbuf_remove.md }
|
- { name: mbuf_remove.md }
|
||||||
- { name: mbuf_resize.md }
|
- { name: mbuf_resize.md }
|
||||||
- { name: mbuf_trim.md }
|
- { name: mbuf_trim.md }
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: "mbuf_append_and_free()"
|
||||||
|
decl_name: "mbuf_append_and_free"
|
||||||
|
symbol_kind: "func"
|
||||||
|
signature: |
|
||||||
|
size_t mbuf_append_and_free(struct mbuf *, void *data, size_t data_size);
|
||||||
|
---
|
||||||
|
|
||||||
|
Appends data to the Mbuf and frees it (data must be heap-allocated).
|
||||||
|
|
||||||
|
Returns the number of bytes appended or 0 if out of memory.
|
||||||
|
data is freed irrespective of return value.
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: "mbuf_clear()"
|
||||||
|
decl_name: "mbuf_clear"
|
||||||
|
symbol_kind: "func"
|
||||||
|
signature: |
|
||||||
|
void mbuf_clear(struct mbuf *);
|
||||||
|
---
|
||||||
|
|
||||||
|
Removes all the data from mbuf (if any).
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: "mbuf_move()"
|
||||||
|
decl_name: "mbuf_move"
|
||||||
|
symbol_kind: "func"
|
||||||
|
signature: |
|
||||||
|
void mbuf_move(struct mbuf *from, struct mbuf *to);
|
||||||
|
---
|
||||||
|
|
||||||
|
Moves the state from one mbuf to the other.
|
||||||
|
|
||||||
@@ -30,7 +30,9 @@ The user-defined event handler will receive following extra events:
|
|||||||
- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
||||||
handshake request. `ev_data` contains parsed HTTP request.
|
handshake request. `ev_data` contains parsed HTTP request.
|
||||||
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
||||||
handshake. `ev_data` is `NULL`.
|
handshake. `ev_data` is a `struct http_message` containing the
|
||||||
|
client's request (server mode) or server's response (client).
|
||||||
|
In client mode handler can examine `resp_code`, which should be 101.
|
||||||
- MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
- MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
||||||
`struct websocket_message *`
|
`struct websocket_message *`
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ signature: |
|
|||||||
struct mg_str data;
|
struct mg_str data;
|
||||||
int status; /* <0 on error */
|
int status; /* <0 on error */
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
/*
|
||||||
|
* User handler can indicate how much of the data was consumed
|
||||||
|
* by setting this variable. By default, it is assumed that all
|
||||||
|
* data has been consumed by the handler.
|
||||||
|
* If not all data was consumed, user's handler will be invoked again later
|
||||||
|
* with the remainder.
|
||||||
|
*/
|
||||||
|
size_t num_data_consumed;
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -16,5 +16,5 @@ that can be, and must be, called from a different (non-IO) thread.
|
|||||||
`func` callback function will be called by the IO thread for each
|
`func` callback function will be called by the IO thread for each
|
||||||
connection. When called, the event will be `MG_EV_POLL`, and a message will
|
connection. When called, the event will be `MG_EV_POLL`, and a message will
|
||||||
be passed as the `ev_data` pointer. Maximum message size is capped
|
be passed as the `ev_data` pointer. Maximum message size is capped
|
||||||
by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
|
by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes by default.
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ title: "mg_mgr_free()"
|
|||||||
decl_name: "mg_mgr_free"
|
decl_name: "mg_mgr_free"
|
||||||
symbol_kind: "func"
|
symbol_kind: "func"
|
||||||
signature: |
|
signature: |
|
||||||
void mg_mgr_free(struct mg_mgr *);
|
void mg_mgr_free(struct mg_mgr *mgr);
|
||||||
---
|
---
|
||||||
|
|
||||||
De-initialises Mongoose manager.
|
De-initialises Mongoose manager.
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ title: "mg_mgr_poll()"
|
|||||||
decl_name: "mg_mgr_poll"
|
decl_name: "mg_mgr_poll"
|
||||||
symbol_kind: "func"
|
symbol_kind: "func"
|
||||||
signature: |
|
signature: |
|
||||||
time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
int mg_mgr_poll(struct mg_mgr *mgr, int milli);
|
||||||
---
|
---
|
||||||
|
|
||||||
This function performs the actual IO and must be called in a loop
|
This function performs the actual IO and must be called in a loop
|
||||||
(an event loop). It returns the current timestamp.
|
(an event loop). It returns number of user events generated (except POLLs).
|
||||||
`milli` is the maximum number of milliseconds to sleep.
|
`milli` is the maximum number of milliseconds to sleep.
|
||||||
`mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
`mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
||||||
of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ signature: |
|
|||||||
struct mbuf send_mbuf; /* Data scheduled for sending */
|
struct mbuf send_mbuf; /* Data scheduled for sending */
|
||||||
time_t last_io_time; /* Timestamp of the last socket IO */
|
time_t last_io_time; /* Timestamp of the last socket IO */
|
||||||
double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
|
double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
void *ssl_if_data; /* SSL library data. */
|
|
||||||
#endif
|
|
||||||
mg_event_handler_t proto_handler; /* Protocol-specific event handler */
|
mg_event_handler_t proto_handler; /* Protocol-specific event handler */
|
||||||
void *proto_data; /* Protocol-specific data */
|
void *proto_data; /* Protocol-specific data */
|
||||||
void (*proto_data_destructor)(void *proto_data);
|
void (*proto_data_destructor)(void *proto_data);
|
||||||
@@ -46,20 +43,30 @@ signature: |
|
|||||||
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
||||||
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
||||||
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
||||||
|
#define MG_F_RECV_AND_CLOSE (1 << 9) /* Drain rx and close the connection. */
|
||||||
|
|
||||||
/* Flags that are settable by user */
|
/* Flags that are settable by user */
|
||||||
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
||||||
#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */
|
#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */
|
||||||
#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
|
|
||||||
#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */
|
/* Flags for protocol handlers */
|
||||||
|
#define MG_F_PROTO_1 (1 << 12)
|
||||||
|
#define MG_F_PROTO_2 (1 << 13)
|
||||||
#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */
|
#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */
|
||||||
|
|
||||||
#define MG_F_USER_1 (1 << 20) /* Flags left for application */
|
/* Flags left for application */
|
||||||
|
#define MG_F_USER_1 (1 << 20)
|
||||||
#define MG_F_USER_2 (1 << 21)
|
#define MG_F_USER_2 (1 << 21)
|
||||||
#define MG_F_USER_3 (1 << 22)
|
#define MG_F_USER_3 (1 << 22)
|
||||||
#define MG_F_USER_4 (1 << 23)
|
#define MG_F_USER_4 (1 << 23)
|
||||||
#define MG_F_USER_5 (1 << 24)
|
#define MG_F_USER_5 (1 << 24)
|
||||||
#define MG_F_USER_6 (1 << 25)
|
#define MG_F_USER_6 (1 << 25)
|
||||||
|
|
||||||
|
#if MG_ENABLE_SSL
|
||||||
|
void *ssl_if_data; /* SSL library data. */
|
||||||
|
#else
|
||||||
|
void *unused_ssl_if_data; /* To keep the size of the structure the same. */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ signature: |
|
|||||||
#endif
|
#endif
|
||||||
void *user_data; /* User data */
|
void *user_data; /* User data */
|
||||||
int num_ifaces;
|
int num_ifaces;
|
||||||
|
int num_calls;
|
||||||
struct mg_iface **ifaces; /* network interfaces */
|
struct mg_iface **ifaces; /* network interfaces */
|
||||||
const char *nameserver; /* DNS server to use */
|
const char *nameserver; /* DNS server to use */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,8 +6,5 @@ signature: |
|
|||||||
struct mg_str mg_url_encode(const struct mg_str src);
|
struct mg_str mg_url_encode(const struct mg_str src);
|
||||||
---
|
---
|
||||||
|
|
||||||
URL-escape the specified string.
|
Same as `mg_url_encode_opt(src, "._-$,;~()/", 0)`.
|
||||||
All non-printable characters are escaped, plus `._-$,;~()/`.
|
|
||||||
Input need not be NUL-terminated, but the returned string is.
|
|
||||||
Returned string is heap-allocated and must be free()'d.
|
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ flags are meant to be set only by the user event handler to tell Mongoose how to
|
|||||||
behave. Below is a list of connection flags that are meant to be set by event
|
behave. Below is a list of connection flags that are meant to be set by event
|
||||||
handlers:
|
handlers:
|
||||||
|
|
||||||
* `MG_F_FINISHED_SENDING_DATA` tells Mongoose that all data has been appended
|
* `MG_F_SEND_AND_CLOSE` tells Mongoose that all data has been appended
|
||||||
to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
|
to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
|
||||||
connection will be closed.
|
connection will be closed.
|
||||||
* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
|
* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ bool bm222_get_data(struct bm222_ctx *ctx) {
|
|||||||
s->y = v[3];
|
s->y = v[3];
|
||||||
s->z = v[5];
|
s->z = v[5];
|
||||||
if (d > max_d) max_d = d;
|
if (d > max_d) max_d = d;
|
||||||
LOG(LL_VERBOSE_DEBUG, ("dx %d dy %d dz %d d %d", dx, dy, dz, d));
|
LOG(LL_VERBOSE_DEBUG,
|
||||||
|
("dx %d dy %d dz %d d %d", (int) dx, (int) dy, (int) dz, (int) d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */
|
return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */
|
||||||
|
|||||||
+84
-14
@@ -1,11 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_CS_DBG_H_
|
#ifndef CS_COMMON_CS_DBG_H_
|
||||||
#define CS_COMMON_CS_DBG_H_
|
#define CS_COMMON_CS_DBG_H_
|
||||||
|
|
||||||
|
#include "common/platform.h"
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -14,6 +28,10 @@
|
|||||||
#define CS_ENABLE_DEBUG 0
|
#define CS_ENABLE_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_LOG_PREFIX_LEN
|
||||||
|
#define CS_LOG_PREFIX_LEN 24
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||||
#endif
|
#endif
|
||||||
@@ -22,6 +40,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log level; `LL_INFO` is the default. Use `cs_log_set_level()` to change it.
|
||||||
|
*/
|
||||||
enum cs_log_level {
|
enum cs_log_level {
|
||||||
LL_NONE = -1,
|
LL_NONE = -1,
|
||||||
LL_ERROR = 0,
|
LL_ERROR = 0,
|
||||||
@@ -34,29 +55,78 @@ enum cs_log_level {
|
|||||||
_LL_MAX = 5,
|
_LL_MAX = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set max log level to print; messages with the level above the given one will
|
||||||
|
* not be printed.
|
||||||
|
*/
|
||||||
void cs_log_set_level(enum cs_log_level level);
|
void cs_log_set_level(enum cs_log_level level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A comma-separated set of prefix=level.
|
||||||
|
* prefix is matched against the log prefix exactly as printed, including line
|
||||||
|
* number, but partial match is ok. Check stops on first matching entry.
|
||||||
|
* If nothing matches, default level is used.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* main.c:=4 - everything from main C at verbose debug level.
|
||||||
|
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cs_log_set_file_level(const char *file_level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function which prints message prefix with the given `level`.
|
||||||
|
* If message should be printed (according to the current log level
|
||||||
|
* and filter), prints the prefix and returns 1, otherwise returns 0.
|
||||||
|
*
|
||||||
|
* Clients should typically just use `LOG()` macro.
|
||||||
|
*/
|
||||||
|
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
|
||||||
|
|
||||||
|
extern enum cs_log_level cs_log_level;
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set file to write logs into. If `NULL`, logs go to `stderr`.
|
||||||
|
*/
|
||||||
void cs_log_set_file(FILE *file);
|
void cs_log_set_file(FILE *file);
|
||||||
|
|
||||||
extern enum cs_log_level cs_log_threshold;
|
/*
|
||||||
void cs_log_print_prefix(const char *func);
|
* Prints log to the current log file, appends "\n" in the end and flushes the
|
||||||
void cs_log_printf(const char *fmt, ...);
|
* stream.
|
||||||
|
*/
|
||||||
|
void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||||
|
|
||||||
#define LOG(l, x) \
|
#if CS_ENABLE_STDIO
|
||||||
if (cs_log_threshold >= l) { \
|
|
||||||
cs_log_print_prefix(__func__); \
|
/*
|
||||||
cs_log_printf x; \
|
* Format and print message `x` with the given level `l`. Example:
|
||||||
}
|
*
|
||||||
|
* ```c
|
||||||
|
* LOG(LL_INFO, ("my info message: %d", 123));
|
||||||
|
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
#define LOG(l, x) \
|
||||||
|
do { \
|
||||||
|
if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
|
||||||
|
cs_log_printf x; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define LOG(l, x) ((void) l)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_NDEBUG
|
#ifndef CS_NDEBUG
|
||||||
|
|
||||||
#define DBG(x) \
|
/*
|
||||||
if (cs_log_threshold >= LL_VERBOSE_DEBUG) { \
|
* Shortcut for `LOG(LL_VERBOSE_DEBUG, (...))`
|
||||||
cs_log_print_prefix(__func__); \
|
*/
|
||||||
cs_log_printf x; \
|
#define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
|
||||||
}
|
|
||||||
|
|
||||||
#else /* NDEBUG */
|
#else /* NDEBUG */
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
#define BM222_ADDR 0x18
|
#define BM222_ADDR 0x18
|
||||||
#define TMP006_ADDR 0x41
|
#define TMP006_ADDR 0x41
|
||||||
|
|
||||||
void fs_slfs_set_new_file_size(const char *name, size_t size);
|
void fs_slfs_set_file_size(const char *name, size_t size);
|
||||||
|
|
||||||
static const char *upload_form =
|
static const char *upload_form =
|
||||||
"\
|
"\
|
||||||
@@ -70,7 +70,7 @@ static struct mg_str upload_fname(struct mg_connection *nc,
|
|||||||
if (nc->user_data != NULL) {
|
if (nc->user_data != NULL) {
|
||||||
intptr_t cl = (intptr_t) nc->user_data;
|
intptr_t cl = (intptr_t) nc->user_data;
|
||||||
if (cl >= 0) {
|
if (cl >= 0) {
|
||||||
fs_slfs_set_new_file_size(fn + 3, cl);
|
fs_slfs_set_file_size(fn + 3, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lfn.len = fname.len + 4;
|
lfn.len = fname.len + 4;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *e) {
|
|||||||
LOG(LL_INFO, ("WiFi: station disconnected"));
|
LOG(LL_INFO, ("WiFi: station disconnected"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(LL_INFO, ("WiFi: event %d", e->Event));
|
LOG(LL_INFO, ("WiFi: event %d", (int) e->Event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *e) {
|
|||||||
} else if (e->Event == SL_NETAPP_IP_LEASED_EVENT) {
|
} else if (e->Event == SL_NETAPP_IP_LEASED_EVENT) {
|
||||||
LOG(LL_INFO, ("IP leased"));
|
LOG(LL_INFO, ("IP leased"));
|
||||||
} else {
|
} else {
|
||||||
LOG(LL_INFO, ("NetApp event %d", e->Event));
|
LOG(LL_INFO, ("NetApp event %d", (int) e->Event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ static int check_pass(const char *user, const char *pass) {
|
|||||||
* or NULL if not found.
|
* or NULL if not found.
|
||||||
*/
|
*/
|
||||||
static struct session *get_session(struct http_message *hm) {
|
static struct session *get_session(struct http_message *hm) {
|
||||||
struct mg_str *cookie_header = mg_get_http_header(hm, "cookie");
|
|
||||||
if (cookie_header == NULL) goto clean;
|
|
||||||
char ssid_buf[21];
|
char ssid_buf[21];
|
||||||
char *ssid = ssid_buf;
|
char *ssid = ssid_buf;
|
||||||
struct session *ret = NULL;
|
struct session *ret = NULL;
|
||||||
|
struct mg_str *cookie_header = mg_get_http_header(hm, "cookie");
|
||||||
|
if (cookie_header == NULL) goto clean;
|
||||||
if (!mg_http_parse_header2(cookie_header, SESSION_COOKIE_NAME, &ssid,
|
if (!mg_http_parse_header2(cookie_header, SESSION_COOKIE_NAME, &ssid,
|
||||||
sizeof(ssid_buf))) {
|
sizeof(ssid_buf))) {
|
||||||
goto clean;
|
goto clean;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ static int s_done = 0;
|
|||||||
static int s_is_connected = 0;
|
static int s_is_connected = 0;
|
||||||
|
|
||||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
|
||||||
(void) nc;
|
(void) nc;
|
||||||
|
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
@@ -26,8 +25,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
||||||
printf("-- Connected\n");
|
struct http_message *hm = (struct http_message *) ev_data;
|
||||||
s_is_connected = 1;
|
if (hm->resp_code == 101) {
|
||||||
|
printf("-- Connected\n");
|
||||||
|
s_is_connected = 1;
|
||||||
|
} else {
|
||||||
|
printf("-- Connection failed! HTTP code %d\n", hm->resp_code);
|
||||||
|
/* Connection will be closed after this. */
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_POLL: {
|
case MG_EV_POLL: {
|
||||||
@@ -66,6 +71,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_WEBSOCKET_FRAME: {
|
case MG_EV_WEBSOCKET_FRAME: {
|
||||||
|
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||||
printf("%.*s\n", (int) wm->size, wm->data);
|
printf("%.*s\n", (int) wm->size, wm->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+1696
-1705
File diff suppressed because it is too large.
Load diff
+303
-248
File diff suppressed because it is too large.
Load diff
+67
-29
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/cs_dbg.h"
|
#include "common/cs_dbg.h"
|
||||||
@@ -12,19 +24,17 @@
|
|||||||
#include "common/cs_time.h"
|
#include "common/cs_time.h"
|
||||||
#include "common/str_util.h"
|
#include "common/str_util.h"
|
||||||
|
|
||||||
enum cs_log_level cs_log_threshold WEAK =
|
enum cs_log_level cs_log_level WEAK =
|
||||||
#if CS_ENABLE_DEBUG
|
#if CS_ENABLE_DEBUG
|
||||||
LL_VERBOSE_DEBUG;
|
LL_VERBOSE_DEBUG;
|
||||||
#else
|
#else
|
||||||
LL_ERROR;
|
LL_ERROR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *s_filter_pattern = NULL;
|
|
||||||
static size_t s_filter_pattern_len;
|
|
||||||
|
|
||||||
void cs_log_set_filter(const char *pattern) WEAK;
|
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
|
static char *s_file_level = NULL;
|
||||||
|
|
||||||
|
void cs_log_set_file_level(const char *file_level) WEAK;
|
||||||
|
|
||||||
FILE *cs_log_file WEAK = NULL;
|
FILE *cs_log_file WEAK = NULL;
|
||||||
|
|
||||||
@@ -34,34 +44,62 @@ double cs_log_ts WEAK;
|
|||||||
|
|
||||||
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
|
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
|
||||||
|
|
||||||
void cs_log_set_filter(const char *pattern) {
|
void cs_log_set_file_level(const char *file_level) {
|
||||||
free(s_filter_pattern);
|
char *fl = s_file_level;
|
||||||
if (pattern != NULL) {
|
if (file_level != NULL) {
|
||||||
s_filter_pattern = strdup(pattern);
|
s_file_level = strdup(file_level);
|
||||||
s_filter_pattern_len = strlen(pattern);
|
|
||||||
} else {
|
} else {
|
||||||
s_filter_pattern = NULL;
|
s_file_level = NULL;
|
||||||
s_filter_pattern_len = 0;
|
|
||||||
}
|
}
|
||||||
|
free(fl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cs_log_print_prefix(enum cs_log_level, const char *, const char *) WEAK;
|
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) WEAK;
|
||||||
int cs_log_print_prefix(enum cs_log_level level, const char *func,
|
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) {
|
||||||
const char *filename) {
|
char prefix[CS_LOG_PREFIX_LEN], *q;
|
||||||
char prefix[21];
|
const char *p;
|
||||||
|
size_t fl = 0, ll = 0, pl = 0;
|
||||||
|
|
||||||
if (level > cs_log_threshold) return 0;
|
if (level > cs_log_level && s_file_level == NULL) return 0;
|
||||||
if (s_filter_pattern != NULL &&
|
|
||||||
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) == 0 &&
|
p = file + strlen(file);
|
||||||
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) == 0) {
|
|
||||||
return 0;
|
while (p != file) {
|
||||||
|
const char c = *(p - 1);
|
||||||
|
if (c == '/' || c == '\\') break;
|
||||||
|
p--;
|
||||||
|
fl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ll = (ln < 10000 ? (ln < 1000 ? (ln < 100 ? (ln < 10 ? 1 : 2) : 3) : 4) : 5);
|
||||||
|
if (fl > (sizeof(prefix) - ll - 2)) fl = (sizeof(prefix) - ll - 2);
|
||||||
|
|
||||||
|
pl = fl + 1 + ll;
|
||||||
|
memcpy(prefix, p, fl);
|
||||||
|
q = prefix + pl;
|
||||||
|
memset(q, ' ', sizeof(prefix) - pl);
|
||||||
|
do {
|
||||||
|
*(--q) = '0' + (ln % 10);
|
||||||
|
ln /= 10;
|
||||||
|
} while (ln > 0);
|
||||||
|
*(--q) = ':';
|
||||||
|
|
||||||
|
if (s_file_level != NULL) {
|
||||||
|
enum cs_log_level pll = cs_log_level;
|
||||||
|
struct mg_str fl = mg_mk_str(s_file_level), ps = MG_MK_STR_N(prefix, pl);
|
||||||
|
struct mg_str k, v;
|
||||||
|
while ((fl = mg_next_comma_list_entry_n(fl, &k, &v)).p != NULL) {
|
||||||
|
bool yes = !(!mg_str_starts_with(ps, k) || v.len == 0);
|
||||||
|
if (!yes) continue;
|
||||||
|
pll = (enum cs_log_level)(*v.p - '0');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (level > pll) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(prefix, func, 20);
|
|
||||||
prefix[20] = '\0';
|
|
||||||
if (cs_log_file == NULL) cs_log_file = stderr;
|
if (cs_log_file == NULL) cs_log_file = stderr;
|
||||||
cs_log_cur_msg_level = level;
|
cs_log_cur_msg_level = level;
|
||||||
fprintf(cs_log_file, "%-20s ", prefix);
|
fwrite(prefix, 1, sizeof(prefix), cs_log_file);
|
||||||
#if CS_LOG_ENABLE_TS_DIFF
|
#if CS_LOG_ENABLE_TS_DIFF
|
||||||
{
|
{
|
||||||
double now = cs_time();
|
double now = cs_time();
|
||||||
@@ -90,15 +128,15 @@ void cs_log_set_file(FILE *file) {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void cs_log_set_filter(const char *pattern) {
|
void cs_log_set_file_level(const char *file_level) {
|
||||||
(void) pattern;
|
(void) file_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CS_ENABLE_STDIO */
|
#endif /* CS_ENABLE_STDIO */
|
||||||
|
|
||||||
void cs_log_set_level(enum cs_log_level level) WEAK;
|
void cs_log_set_level(enum cs_log_level level) WEAK;
|
||||||
void cs_log_set_level(enum cs_log_level level) {
|
void cs_log_set_level(enum cs_log_level level) {
|
||||||
cs_log_threshold = level;
|
cs_log_level = level;
|
||||||
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
|
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
|
||||||
cs_log_ts = cs_time();
|
cs_log_ts = cs_time();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+44
-45
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_CS_DBG_H_
|
#ifndef CS_COMMON_CS_DBG_H_
|
||||||
@@ -16,6 +28,10 @@
|
|||||||
#define CS_ENABLE_DEBUG 0
|
#define CS_ENABLE_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_LOG_PREFIX_LEN
|
||||||
|
#define CS_LOG_PREFIX_LEN 24
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||||
#endif
|
#endif
|
||||||
@@ -46,51 +62,28 @@ enum cs_log_level {
|
|||||||
void cs_log_set_level(enum cs_log_level level);
|
void cs_log_set_level(enum cs_log_level level);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set log filter. NULL (a default) logs everything.
|
* A comma-separated set of prefix=level.
|
||||||
* Otherwise, function name and file name will be tested against the given
|
* prefix is matched against the log prefix exactly as printed, including line
|
||||||
* pattern, and only matching messages will be printed.
|
* number, but partial match is ok. Check stops on first matching entry.
|
||||||
|
* If nothing matches, default level is used.
|
||||||
*
|
*
|
||||||
* For the pattern syntax, refer to `mg_match_prefix()` in `str_util.h`.
|
* Examples:
|
||||||
|
* main.c:=4 - everything from main C at verbose debug level.
|
||||||
|
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
|
||||||
*
|
*
|
||||||
* Example:
|
|
||||||
* ```c
|
|
||||||
* void foo(void) {
|
|
||||||
* LOG(LL_INFO, ("hello from foo"));
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* void bar(void) {
|
|
||||||
* LOG(LL_INFO, ("hello from bar"));
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* void test(void) {
|
|
||||||
* cs_log_set_filter(NULL);
|
|
||||||
* foo();
|
|
||||||
* bar();
|
|
||||||
*
|
|
||||||
* cs_log_set_filter("f*");
|
|
||||||
* foo();
|
|
||||||
* bar(); // Will NOT print anything
|
|
||||||
*
|
|
||||||
* cs_log_set_filter("bar");
|
|
||||||
* foo(); // Will NOT print anything
|
|
||||||
* bar();
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
void cs_log_set_filter(const char *pattern);
|
void cs_log_set_file_level(const char *file_level);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function which prints message prefix with the given `level`, function
|
* Helper function which prints message prefix with the given `level`.
|
||||||
* name `func` and `filename`. If message should be printed (accordingly to the
|
* If message should be printed (according to the current log level
|
||||||
* current log level and filter), prints the prefix and returns 1, otherwise
|
* and filter), prints the prefix and returns 1, otherwise returns 0.
|
||||||
* returns 0.
|
|
||||||
*
|
*
|
||||||
* Clients should typically just use `LOG()` macro.
|
* Clients should typically just use `LOG()` macro.
|
||||||
*/
|
*/
|
||||||
int cs_log_print_prefix(enum cs_log_level level, const char *func,
|
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
|
||||||
const char *filename);
|
|
||||||
|
|
||||||
extern enum cs_log_level cs_log_threshold;
|
extern enum cs_log_level cs_log_level;
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
|
|
||||||
@@ -103,11 +96,9 @@ void cs_log_set_file(FILE *file);
|
|||||||
* Prints log to the current log file, appends "\n" in the end and flushes the
|
* Prints log to the current log file, appends "\n" in the end and flushes the
|
||||||
* stream.
|
* stream.
|
||||||
*/
|
*/
|
||||||
void cs_log_printf(const char *fmt, ...)
|
void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||||
#ifdef __GNUC__
|
|
||||||
__attribute__((format(printf, 1, 2)))
|
#if CS_ENABLE_STDIO
|
||||||
#endif
|
|
||||||
;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format and print message `x` with the given level `l`. Example:
|
* Format and print message `x` with the given level `l`. Example:
|
||||||
@@ -117,11 +108,19 @@ void cs_log_printf(const char *fmt, ...)
|
|||||||
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
#define LOG(l, x) \
|
#define LOG(l, x) \
|
||||||
do { \
|
do { \
|
||||||
if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \
|
if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
|
||||||
|
cs_log_printf x; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define LOG(l, x) ((void) l)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_NDEBUG
|
#ifndef CS_NDEBUG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+13
-1
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_MD5_H_
|
#ifndef CS_COMMON_MD5_H_
|
||||||
|
|||||||
+13
-1
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/cs_time.h"
|
#include "common/cs_time.h"
|
||||||
|
|||||||
+13
-1
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_CS_TIME_H_
|
#ifndef CS_COMMON_CS_TIME_H_
|
||||||
|
|||||||
+13
-1
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_MG_MEM_H_
|
#ifndef CS_COMMON_MG_MEM_H_
|
||||||
|
|||||||
+20
-2
@@ -22,8 +22,9 @@
|
|||||||
#define CS_P_NRF51 12
|
#define CS_P_NRF51 12
|
||||||
#define CS_P_NRF52 10
|
#define CS_P_NRF52 10
|
||||||
#define CS_P_PIC32 11
|
#define CS_P_PIC32 11
|
||||||
|
#define CS_P_RS14100 18
|
||||||
#define CS_P_STM32 16
|
#define CS_P_STM32 16
|
||||||
/* Next id: 18 */
|
/* Next id: 19 */
|
||||||
|
|
||||||
/* If not specified explicitly, we guess platform by defines. */
|
/* If not specified explicitly, we guess platform by defines. */
|
||||||
#ifndef CS_PLATFORM
|
#ifndef CS_PLATFORM
|
||||||
@@ -55,6 +56,8 @@
|
|||||||
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
|
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
|
||||||
defined(TARGET_IS_TM4C129_RA2)
|
defined(TARGET_IS_TM4C129_RA2)
|
||||||
#define CS_PLATFORM CS_P_TM4C129
|
#define CS_PLATFORM CS_P_TM4C129
|
||||||
|
#elif defined(RS14100)
|
||||||
|
#define CS_PLATFORM CS_P_RS14100
|
||||||
#elif defined(STM32)
|
#elif defined(STM32)
|
||||||
#define CS_PLATFORM CS_P_STM32
|
#define CS_PLATFORM CS_P_STM32
|
||||||
#endif
|
#endif
|
||||||
@@ -69,6 +72,7 @@
|
|||||||
#define MG_NET_IF_SIMPLELINK 2
|
#define MG_NET_IF_SIMPLELINK 2
|
||||||
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
||||||
#define MG_NET_IF_PIC32 4
|
#define MG_NET_IF_PIC32 4
|
||||||
|
#define MG_NET_IF_NULL 5
|
||||||
|
|
||||||
#define MG_SSL_IF_OPENSSL 1
|
#define MG_SSL_IF_OPENSSL 1
|
||||||
#define MG_SSL_IF_MBEDTLS 2
|
#define MG_SSL_IF_MBEDTLS 2
|
||||||
@@ -88,12 +92,26 @@
|
|||||||
#include "common/platforms/platform_nxp_lpc.h"
|
#include "common/platforms/platform_nxp_lpc.h"
|
||||||
#include "common/platforms/platform_nxp_kinetis.h"
|
#include "common/platforms/platform_nxp_kinetis.h"
|
||||||
#include "common/platforms/platform_pic32.h"
|
#include "common/platforms/platform_pic32.h"
|
||||||
|
#include "common/platforms/platform_rs14100.h"
|
||||||
#include "common/platforms/platform_stm32.h"
|
#include "common/platforms/platform_stm32.h"
|
||||||
|
#if CS_PLATFORM == CS_P_CUSTOM
|
||||||
|
#include <platform_custom.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Common stuff */
|
/* Common stuff */
|
||||||
|
|
||||||
|
#if !defined(PRINTF_LIKE)
|
||||||
|
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||||||
|
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||||||
|
#else
|
||||||
|
#define PRINTF_LIKE(f, a)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(WEAK)
|
#if !defined(WEAK)
|
||||||
#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
|
#if (defined(__GNUC__) || defined(__clang__) || \
|
||||||
|
defined(__TI_COMPILER_VERSION__)) && \
|
||||||
|
!defined(_WIN32)
|
||||||
#define WEAK __attribute__((weak))
|
#define WEAK __attribute__((weak))
|
||||||
#else
|
#else
|
||||||
#define WEAK
|
#define WEAK
|
||||||
|
|||||||
@@ -1,8 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arm_exc.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -15,33 +29,11 @@
|
|||||||
#include "mgos_core_dump.h"
|
#include "mgos_core_dump.h"
|
||||||
#include "mgos_hal.h"
|
#include "mgos_hal.h"
|
||||||
|
|
||||||
struct arm_exc_frame {
|
#ifndef MGOS_ENABLE_CORE_DUMP
|
||||||
uint32_t r0;
|
#define MGOS_ENABLE_CORE_DUMP 1
|
||||||
uint32_t r1;
|
|
||||||
uint32_t r2;
|
|
||||||
uint32_t r3;
|
|
||||||
uint32_t r12;
|
|
||||||
uint32_t lr;
|
|
||||||
uint32_t pc;
|
|
||||||
uint32_t xpsr;
|
|
||||||
#ifdef ARM_HAVE_FPU
|
|
||||||
uint32_t s[16];
|
|
||||||
uint32_t fpscr;
|
|
||||||
uint32_t reserved;
|
|
||||||
#endif
|
#endif
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct arm_gdb_reg_file {
|
#if __FPU_PRESENT && !defined(MGOS_BOOT_BUILD)
|
||||||
uint32_t r[13];
|
|
||||||
uint32_t sp;
|
|
||||||
uint32_t lr;
|
|
||||||
uint32_t pc;
|
|
||||||
uint32_t cpsr;
|
|
||||||
uint64_t d[16];
|
|
||||||
uint32_t fpscr;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
#if ARM_HAVE_FPU
|
|
||||||
static void save_s16_s31(uint32_t *dst) {
|
static void save_s16_s31(uint32_t *dst) {
|
||||||
__asm volatile(
|
__asm volatile(
|
||||||
"\
|
"\
|
||||||
@@ -75,16 +67,25 @@ static void print_fpu_regs(const uint32_t *regs, int off, int n) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static struct arm_gdb_reg_file *s_rf = NULL;
|
||||||
|
|
||||||
|
void arm_exc_dump_regs(void) {
|
||||||
|
mgos_cd_write_section(MGOS_CORE_DUMP_SECTION_REGS, s_rf, sizeof(*s_rf));
|
||||||
|
}
|
||||||
|
|
||||||
void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
||||||
struct arm_gdb_reg_file *rf) {
|
struct arm_gdb_reg_file *rf) {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
const char *name;
|
const char *name;
|
||||||
|
#if __MPU_PRESENT
|
||||||
|
MPU->CTRL = 0; // Disable MPU.
|
||||||
|
#endif
|
||||||
portDISABLE_INTERRUPTS();
|
portDISABLE_INTERRUPTS();
|
||||||
|
s_rf = rf;
|
||||||
switch (isr_no) {
|
switch (isr_no) {
|
||||||
case 0:
|
case 0:
|
||||||
name = "ThreadMode";
|
name = "ThreadMode";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
@@ -93,7 +94,6 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
case 13:
|
case 13:
|
||||||
name = "Reserved";
|
name = "Reserved";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
name = "NMI";
|
name = "NMI";
|
||||||
break;
|
break;
|
||||||
@@ -122,24 +122,30 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
name = "SysTick";
|
name = "SysTick";
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
|
#ifndef MGOS_BOOT_BUILD
|
||||||
sprintf(buf, "IRQ%u", isr_no - 16);
|
sprintf(buf, "IRQ%u", isr_no - 16);
|
||||||
|
#endif
|
||||||
name = buf;
|
name = buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mgos_cd_printf("\n\n--- Exception %u (%s) ---\n", isr_no, name);
|
mgos_cd_printf("\n\n--- Exception %u (%s) ---\n", isr_no, name);
|
||||||
if (rf != NULL) {
|
if (rf != NULL) {
|
||||||
mgos_cd_printf(" R0: 0x%08lx R1: 0x%08lx R2: 0x%08lx R3: 0x%08lx\n",
|
mgos_cd_printf(
|
||||||
rf->r[0], rf->r[1], rf->r[2], rf->r[3]);
|
" R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx\n", 0,
|
||||||
mgos_cd_printf(" R4: 0x%08lx R5: 0x%08lx R6: 0x%08lx R7: 0x%08lx\n",
|
rf->r[0], 1, rf->r[1], 2, rf->r[2], 3, rf->r[3]);
|
||||||
rf->r[4], rf->r[5], rf->r[6], rf->r[7]);
|
mgos_cd_printf(
|
||||||
|
" R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx\n", 4,
|
||||||
|
rf->r[4], 5, rf->r[5], 6, rf->r[6], 7, rf->r[7]);
|
||||||
mgos_cd_printf(" R8: 0x%08lx R9: 0x%08lx R10: 0x%08lx R11: 0x%08lx\n",
|
mgos_cd_printf(" R8: 0x%08lx R9: 0x%08lx R10: 0x%08lx R11: 0x%08lx\n",
|
||||||
rf->r[8], rf->r[9], rf->r[10], rf->r[11]);
|
rf->r[8], rf->r[9], rf->r[10], rf->r[11]);
|
||||||
mgos_cd_printf(" R12: 0x%08lx SP: 0x%08lx LR: 0x%08lx PC: 0x%08lx\n",
|
mgos_cd_printf(" R12: 0x%08lx SP: 0x%08lx LR: 0x%08lx PC: 0x%08lx\n",
|
||||||
rf->r[12], rf->sp, rf->lr, rf->pc);
|
rf->r[12], rf->sp, rf->lr, rf->pc);
|
||||||
mgos_cd_printf(" PSR: 0x%08lx\n", rf->cpsr);
|
mgos_cd_printf(" PSR: 0x%08lx MSP: 0x%08lx PSP: 0x%08lx\n", rf->xpsr,
|
||||||
|
rf->msp, rf->psp);
|
||||||
}
|
}
|
||||||
|
#if __FPU_PRESENT
|
||||||
memset(rf->d, 0, sizeof(rf->d));
|
memset(rf->d, 0, sizeof(rf->d));
|
||||||
#if ARM_HAVE_FPU
|
#if !defined(MGOS_BOOT_BUILD)
|
||||||
rf->fpscr = ef->fpscr;
|
rf->fpscr = ef->fpscr;
|
||||||
memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s));
|
memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s));
|
||||||
print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s));
|
print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s));
|
||||||
@@ -152,10 +158,10 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
#else
|
#else
|
||||||
rf->fpscr = 0;
|
rf->fpscr = 0;
|
||||||
#endif
|
#endif
|
||||||
mgos_cd_emit_header();
|
#endif
|
||||||
mgos_cd_emit_section(MGOS_CORE_DUMP_SECTION_REGS, rf, sizeof(*rf));
|
#if MGOS_ENABLE_CORE_DUMP
|
||||||
mgos_cd_emit_section("SRAM", (void *) SRAM_BASE_ADDR, SRAM_SIZE);
|
mgos_cd_write();
|
||||||
mgos_cd_emit_footer();
|
#endif
|
||||||
#ifdef MGOS_HALT_ON_EXCEPTION
|
#ifdef MGOS_HALT_ON_EXCEPTION
|
||||||
mgos_cd_printf("Halting\n");
|
mgos_cd_printf("Halting\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -165,4 +171,5 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
mgos_cd_printf("Rebooting\n");
|
mgos_cd_printf("Rebooting\n");
|
||||||
mgos_dev_system_restart();
|
mgos_dev_system_restart();
|
||||||
#endif
|
#endif
|
||||||
|
(void) ef;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2019 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct arm_exc_frame {
|
||||||
|
uint32_t r0;
|
||||||
|
uint32_t r1;
|
||||||
|
uint32_t r2;
|
||||||
|
uint32_t r3;
|
||||||
|
uint32_t r12;
|
||||||
|
uint32_t lr;
|
||||||
|
uint32_t pc;
|
||||||
|
uint32_t xpsr;
|
||||||
|
#if __FPU_PRESENT
|
||||||
|
uint32_t s[16];
|
||||||
|
uint32_t fpscr;
|
||||||
|
uint32_t reserved;
|
||||||
|
#endif
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct arm_gdb_reg_file {
|
||||||
|
uint32_t r[13];
|
||||||
|
uint32_t sp;
|
||||||
|
uint32_t lr;
|
||||||
|
uint32_t pc;
|
||||||
|
uint32_t xpsr;
|
||||||
|
#if __FPU_PRESENT
|
||||||
|
uint64_t d[16];
|
||||||
|
uint32_t fpscr;
|
||||||
|
#endif
|
||||||
|
// MSP and PSP are our extension.
|
||||||
|
uint32_t msp;
|
||||||
|
uint32_t psp;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
||||||
|
struct arm_gdb_reg_file *rf);
|
||||||
|
void arm_exc_dump_regs(void);
|
||||||
@@ -28,12 +28,12 @@ arm_exc_handler_top:
|
|||||||
mrseq r1, msp
|
mrseq r1, msp
|
||||||
mrsne r1, psp
|
mrsne r1, psp
|
||||||
// r1 -> arm_exc_frame prepared for us by the CPU
|
// r1 -> arm_exc_frame prepared for us by the CPU
|
||||||
#if ARM_HAVE_FPU
|
#if __FPU_PRESENT
|
||||||
add r0, r1, #104 // sizeof(arm_exc_frame)
|
add r0, r1, #104 // sizeof(arm_exc_frame)
|
||||||
sub sp, #328 // sizeof(arm_gdb_reg_file)
|
sub sp, #208 // sizeof(arm_gdb_reg_file)
|
||||||
#else
|
#else
|
||||||
add r0, r1, #32 // sizeof(arm_exc_frame)
|
add r0, r1, #32 // sizeof(arm_exc_frame)
|
||||||
sub sp, #328 // sizeof(arm_gdb_reg_file)
|
sub sp, #76 // sizeof(arm_gdb_reg_file)
|
||||||
#endif
|
#endif
|
||||||
mov r2, sp
|
mov r2, sp
|
||||||
// r0 -> original sp, r2 -> arm_gdb_reg_file to fill
|
// r0 -> original sp, r2 -> arm_gdb_reg_file to fill
|
||||||
@@ -63,6 +63,17 @@ arm_exc_handler_top:
|
|||||||
str r3, [r2, #60]
|
str r3, [r2, #60]
|
||||||
ldr r3, [r1, #28] // xpsr
|
ldr r3, [r1, #28] // xpsr
|
||||||
str r3, [r2, #64]
|
str r3, [r2, #64]
|
||||||
|
#if __FPU_PRESENT
|
||||||
|
mrs r3, msp
|
||||||
|
str r3, [r2, #200] // msp
|
||||||
|
mrs r3, psp
|
||||||
|
str r3, [r2, #204] // psp
|
||||||
|
#else
|
||||||
|
mrs r3, msp
|
||||||
|
str r3, [r2, #68] // msp
|
||||||
|
mrs r3, psp
|
||||||
|
str r3, [r2, #72] // psp
|
||||||
|
#endif
|
||||||
|
|
||||||
mrs r0, ipsr
|
mrs r0, ipsr
|
||||||
b arm_exc_handler_bottom
|
b arm_exc_handler_bottom
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
#include "mgos_system.h"
|
||||||
|
|
||||||
|
void (*mgos_nsleep100)(uint32_t n);
|
||||||
|
uint32_t mgos_nsleep100_loop_count = 0;
|
||||||
|
/* Provided by arm_nsleep100_{m4,m7}.S for M4 and M7 respectively. */
|
||||||
|
extern void mgos_nsleep100_impl(uint32_t n);
|
||||||
|
|
||||||
|
void mgos_nsleep100_cal(void) {
|
||||||
|
uint32_t cpu_freq = mgos_get_cpu_freq();
|
||||||
|
/* # of instruction cycles per 100 ns */
|
||||||
|
mgos_nsleep100_loop_count =
|
||||||
|
roundf((100.0f / 1000000000.0f) / (1.0f / cpu_freq));
|
||||||
|
mgos_nsleep100 = mgos_nsleep100_impl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2019 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.arch armv7e-m
|
||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
/* These are required to satisfy TI linker. */
|
||||||
|
.eabi_attribute Tag_ABI_align_needed, 1
|
||||||
|
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||||
|
|
||||||
|
.global mgos_nsleep100_impl
|
||||||
|
.global mgos_nsleep100_loop_count
|
||||||
|
|
||||||
|
.section .text.IRAM.mgos_nsleep100_impl
|
||||||
|
.type mgos_nsleep100_impl, %function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
mgos_nsleep100_impl:
|
||||||
|
ldr r3, =mgos_nsleep100_loop_count
|
||||||
|
ldr r3, [r3]
|
||||||
|
mul r0, r3
|
||||||
|
mov r1, #6
|
||||||
|
udiv r0, r0, r1
|
||||||
|
cbz r0, xxx
|
||||||
|
lxx:
|
||||||
|
subs r0, #1
|
||||||
|
bne lxx
|
||||||
|
xxx:
|
||||||
|
bx lr
|
||||||
|
.align 4
|
||||||
|
.size mgos_nsleep100_impl, . - mgos_nsleep100_impl
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.arch armv7e-m
|
||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
/* These are required to satisfy TI linker. */
|
||||||
|
.eabi_attribute Tag_ABI_align_needed, 1
|
||||||
|
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||||
|
|
||||||
|
.global mgos_nsleep100_impl
|
||||||
|
.global mgos_nsleep100_loop_count
|
||||||
|
|
||||||
|
#if defined(TARGET_IS_CC3200) || defined(TARGET_IS_CC3220)
|
||||||
|
.section .iram.mgos_nsleep100_impl
|
||||||
|
#else
|
||||||
|
.section .text.IRAM.mgos_nsleep100_impl
|
||||||
|
#endif
|
||||||
|
.type mgos_nsleep100_impl, %function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
mgos_nsleep100_impl:
|
||||||
|
ldr r3, =mgos_nsleep100_loop_count
|
||||||
|
ldr r3, [r3]
|
||||||
|
mul r0, r3
|
||||||
|
#if defined(STM32L4)
|
||||||
|
mov r1, #3
|
||||||
|
#else
|
||||||
|
mov r1, #6
|
||||||
|
#endif
|
||||||
|
udiv r0, r0, r1
|
||||||
|
cbz r0, mgos_nsleep100_impl_out
|
||||||
|
mgos_nsleep100_impl_loop:
|
||||||
|
subs r0, #1
|
||||||
|
bne mgos_nsleep100_impl_loop
|
||||||
|
mgos_nsleep100_impl_out:
|
||||||
|
bx lr
|
||||||
|
.align 4
|
||||||
|
.size mgos_nsleep100_impl, . - mgos_nsleep100_impl
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.arch armv7e-m
|
||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
/* These are required to satisfy TI linker. */
|
||||||
|
.eabi_attribute Tag_ABI_align_needed, 1
|
||||||
|
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||||
|
|
||||||
|
.global mgos_nsleep100_impl
|
||||||
|
.global mgos_nsleep100_loop_count
|
||||||
|
|
||||||
|
.section .text.IRAM.mgos_nsleep100_impl
|
||||||
|
.type mgos_nsleep100_impl, %function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
mgos_nsleep100_impl:
|
||||||
|
ldr r3, =mgos_nsleep100_loop_count
|
||||||
|
ldr r3, [r3]
|
||||||
|
/* Because of speculative fetch, the core loop only takes 1 cycle. */
|
||||||
|
muls r0, r3
|
||||||
|
cbz r0, xxx
|
||||||
|
lxx:
|
||||||
|
subs r0, #1
|
||||||
|
bne lxx
|
||||||
|
xxx:
|
||||||
|
bx lr
|
||||||
|
.align 4
|
||||||
|
.size mgos_nsleep100_impl, . - mgos_nsleep100_impl
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if CS_PLATFORM == CS_P_CC3200
|
#if CS_PLATFORM == CS_P_CC3200
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ $(SDK_OBJS): CFLAGS += -include common/platform.h
|
|||||||
|
|
||||||
# cc flags,file
|
# cc flags,file
|
||||||
define cc
|
define cc
|
||||||
$(vecho) "GCC $2 -> $@"
|
$(vecho) "GCC $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c $1 -o $@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c $1 -o $@ $2
|
||||||
endef
|
endef
|
||||||
define cxx
|
define cxx
|
||||||
$(vecho) "G++ $2 -> $@"
|
$(vecho) "G++ $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CXX) -c $1 -o $@ $2
|
$(Q) $(CC_WRAPPER) $(CXX) -c $1 -o $@ $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|||||||
@@ -17,17 +17,17 @@ CXXFLAGS += $(TI_C_CXX_FLAGS) $(C_CXX_FLAGS)
|
|||||||
|
|
||||||
# cc flags,file
|
# cc flags,file
|
||||||
define cc
|
define cc
|
||||||
$(vecho) "TICC $2 -> $@"
|
$(vecho) "TICC $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
||||||
endef
|
endef
|
||||||
define cxx
|
define cxx
|
||||||
$(vecho) "TICXX $2 -> $@"
|
$(vecho) "TICXX $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# asm flags,file
|
# asm flags,file
|
||||||
define asm
|
define asm
|
||||||
$(vecho) "TIASM $2 -> $@"
|
$(vecho) "TIASM $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c $1 --output_file=$@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c $1 --output_file=$@ $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* Spiffy flasher. Implements strong checksums (MD5) and can use higher
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
* baud rates. Actual max baud rate will differe from device to device,
|
* you may not use this file except in compliance with the License.
|
||||||
* but 921K seems to be common.
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* SLIP protocol is used for communication.
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* First packet is a single byte - command number.
|
|
||||||
* After that, a packet with a variable number of 32-bit (LE) arguments,
|
|
||||||
* depending on command.
|
|
||||||
*
|
*
|
||||||
* Then command produces variable number of packets of output, but first
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* packet of length 1 is the response code: 0 for success, non-zero - error.
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
*
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See individual command description below.
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stub_flasher.h"
|
#include "stub_flasher.h"
|
||||||
@@ -27,7 +25,7 @@
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include "eagle_soc.h"
|
#include "eagle_soc.h"
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
#include "../../../miniz.c"
|
#include "miniz.c"
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include "rom/efuse.h"
|
#include "rom/efuse.h"
|
||||||
#include "rom/miniz.h"
|
#include "rom/miniz.h"
|
||||||
@@ -40,7 +38,7 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
/* Param: baud rate. */
|
/* Param: baud rate. */
|
||||||
uint32_t params[1] __attribute__((section(".params")));
|
uint32_t params[2] __attribute__((section(".params")));
|
||||||
|
|
||||||
#define FLASH_BLOCK_SIZE 65536
|
#define FLASH_BLOCK_SIZE 65536
|
||||||
#define FLASH_SECTOR_SIZE 4096
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
@@ -472,6 +470,27 @@ uint8_t cmd_loop(void) {
|
|||||||
resp = 0;
|
resp = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_READ_REG: {
|
||||||
|
len = SLIP_recv(args, sizeof(args));
|
||||||
|
if (len == 4) {
|
||||||
|
uint32_t value = READ_PERI_REG((uint32_t *) args[0]);
|
||||||
|
SLIP_send(&value, sizeof(value));
|
||||||
|
resp = 0;
|
||||||
|
} else {
|
||||||
|
resp = 0x91;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_WRITE_REG: {
|
||||||
|
len = SLIP_recv(args, sizeof(args));
|
||||||
|
if (len == 8) {
|
||||||
|
WRITE_PERI_REG((uint32_t *) args[0], args[1]);
|
||||||
|
resp = 0;
|
||||||
|
} else {
|
||||||
|
resp = 0xa1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SLIP_send(&resp, 1);
|
SLIP_send(&resp, 1);
|
||||||
} while (cmd != CMD_BOOT_FW && cmd != CMD_REBOOT);
|
} while (cmd != CMD_BOOT_FW && cmd != CMD_REBOOT);
|
||||||
@@ -479,8 +498,7 @@ uint8_t cmd_loop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stub_main1(void) {
|
void stub_main1(void) {
|
||||||
uint32_t baud_rate = params[0];
|
uint32_t old_baud_rate = params[0], new_baud_rate = params[1];
|
||||||
uint32_t greeting = 0x4941484f; /* OHAI */
|
|
||||||
uint8_t last_cmd;
|
uint8_t last_cmd;
|
||||||
|
|
||||||
/* This points at us right now, reset for next boot. */
|
/* This points at us right now, reset for next boot. */
|
||||||
@@ -489,6 +507,7 @@ void stub_main1(void) {
|
|||||||
/* Selects SPI functions for flash pins. */
|
/* Selects SPI functions for flash pins. */
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
SelectSpiFunction();
|
SelectSpiFunction();
|
||||||
|
spi_flash_attach();
|
||||||
SET_PERI_REG_MASK(0x3FF00014, 1); /* Switch to 160 MHz */
|
SET_PERI_REG_MASK(0x3FF00014, 1); /* Switch to 160 MHz */
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), 0 /* legacy */);
|
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), 0 /* legacy */);
|
||||||
@@ -498,9 +517,10 @@ void stub_main1(void) {
|
|||||||
0 /* deviceId */, 16 * 1024 * 1024 /* chip_size */, FLASH_BLOCK_SIZE,
|
0 /* deviceId */, 16 * 1024 * 1024 /* chip_size */, FLASH_BLOCK_SIZE,
|
||||||
FLASH_SECTOR_SIZE, FLASH_PAGE_SIZE, 0xffff /* status_mask */);
|
FLASH_SECTOR_SIZE, FLASH_PAGE_SIZE, 0xffff /* status_mask */);
|
||||||
|
|
||||||
if (baud_rate > 0) {
|
uint32_t old_div = 0;
|
||||||
|
if (new_baud_rate > 0) {
|
||||||
ets_delay_us(10000);
|
ets_delay_us(10000);
|
||||||
set_baud_rate(0, baud_rate);
|
old_div = set_baud_rate(0, old_baud_rate, new_baud_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give host time to get ready too. */
|
/* Give host time to get ready too. */
|
||||||
@@ -511,7 +531,7 @@ void stub_main1(void) {
|
|||||||
WRITE_PERI_REG(UART_FIFO_REG(0), 0x55);
|
WRITE_PERI_REG(UART_FIFO_REG(0), 0x55);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
SLIP_send(&greeting, 4);
|
SLIP_send(&old_div, 4);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
last_cmd = cmd_loop();
|
last_cmd = cmd_loop();
|
||||||
@@ -527,7 +547,7 @@ void stub_main1(void) {
|
|||||||
* then jumps to 0x4000108a, then checks strapping bits again (which will
|
* then jumps to 0x4000108a, then checks strapping bits again (which will
|
||||||
* not have changed), and then proceeds to 0x400010a8.
|
* not have changed), and then proceeds to 0x400010a8.
|
||||||
*/
|
*/
|
||||||
volatile uint32_t *sp = &baud_rate;
|
volatile uint32_t *sp = &old_baud_rate;
|
||||||
while (*sp != (uint32_t) 0x40001100) sp++;
|
while (*sp != (uint32_t) 0x40001100) sp++;
|
||||||
*sp = 0x400010a8;
|
*sp = 0x400010a8;
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -91,6 +91,24 @@ enum stub_cmd {
|
|||||||
* Output: arguments.
|
* Output: arguments.
|
||||||
*/
|
*/
|
||||||
CMD_ECHO = 8,
|
CMD_ECHO = 8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read register value.
|
||||||
|
*
|
||||||
|
* Args: register address.
|
||||||
|
* Input: None.
|
||||||
|
* Output: register value.
|
||||||
|
*/
|
||||||
|
CMD_READ_REG = 9,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write register value.
|
||||||
|
*
|
||||||
|
* Args: register address, value.
|
||||||
|
* Input: None.
|
||||||
|
* Output: None.
|
||||||
|
*/
|
||||||
|
CMD_WRITE_REG = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_ */
|
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_ */
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "soc/gpio_reg.h"
|
#include "soc/gpio_reg.h"
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -42,5 +42,10 @@ SECTIONS {
|
|||||||
INCLUDE "components/esp32/ld/esp32.rom.ld"
|
INCLUDE "components/esp32/ld/esp32.rom.ld"
|
||||||
INCLUDE "components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
INCLUDE "components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
||||||
|
|
||||||
|
PROVIDE(ets_isr_mask = 0x400067fc);
|
||||||
|
PROVIDE(ets_isr_unmask = 0x40006808);
|
||||||
|
PROVIDE(MD5Init = 0x4005da7c);
|
||||||
|
PROVIDE(MD5Update = 0x4005da9c);
|
||||||
|
PROVIDE(MD5Final = 0x4005db1c);
|
||||||
PROVIDE(esp_rom_spiflash_attach = 0x40062a6c);
|
PROVIDE(esp_rom_spiflash_attach = 0x40062a6c);
|
||||||
PROVIDE(esp_rom_spiflash_config_clk = 0x40062bc8);
|
PROVIDE(esp_rom_spiflash_config_clk = 0x40062bc8);
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* Stub template.
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
#include "rom_functions.h"
|
#include "rom_functions.h"
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate) {
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
uint32_t master_freq = ets_get_detected_xtal_freq() << 4;
|
uint32_t new_baud_rate) {
|
||||||
master_freq += (baud_rate / 2);
|
uint32_t uart_reg = REG_READ(UART_CLKDIV_REG(uart_no));
|
||||||
uint32_t div = master_freq / baud_rate;
|
uint32_t uart_div = uart_reg & UART_CLKDIV_M;
|
||||||
uart_div_modify(uart_no, div);
|
uint32_t fraction = (uart_reg >> UART_CLKDIV_FRAG_S) & UART_CLKDIV_FRAG_V;
|
||||||
|
uart_div = (uart_div << 4) + fraction;
|
||||||
|
uint32_t master_freq = uart_div * old_baud_rate;
|
||||||
|
uart_div_modify(uart_no, master_freq / new_baud_rate);
|
||||||
|
return uart_div;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_
|
#ifndef CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_
|
||||||
@@ -8,6 +20,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate);
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
|
uint32_t new_baud_rate);
|
||||||
|
|
||||||
#endif /* CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_ */
|
#endif /* CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_ */
|
||||||
@@ -25,7 +25,7 @@ $(Q) $(CC_WRAPPER) $(LD) $(LIBDIRS) -T$(LD_SCRIPT) $(LDFLAGS) -o $@ \
|
|||||||
endef
|
endef
|
||||||
|
|
||||||
define compile_params
|
define compile_params
|
||||||
$(vecho) "$5 $1 -> $2"
|
$(vecho) "$5 $1"
|
||||||
$(Q) $(CC_WRAPPER) $3 -MD -MP $(INCDIRS) $4 -c $1 -o $2
|
$(Q) $(CC_WRAPPER) $3 -MD -MP $(INCDIRS) $4 -c $1 -o $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
@@ -57,7 +57,8 @@ NO_Os_FLAGS= -fno-expensive-optimizations -fno-thread-jumps \
|
|||||||
-fno-tree-pre -fno-tree-vrp
|
-fno-tree-pre -fno-tree-vrp
|
||||||
|
|
||||||
C_CXX_FLAGS = -W -Wall -Werror -Wundef -Wno-comment -Wno-variadic-macros -Wpointer-arith \
|
C_CXX_FLAGS = -W -Wall -Werror -Wundef -Wno-comment -Wno-variadic-macros -Wpointer-arith \
|
||||||
-Os $(NO_Os_FLAGS) -g3 \
|
-Wno-missing-field-initializers \
|
||||||
|
-pipe -Os $(NO_Os_FLAGS) -g3 \
|
||||||
-Wl,-EL -fno-inline-functions \
|
-Wl,-EL -fno-inline-functions \
|
||||||
-D_XOPEN_SOURCE=500 \
|
-D_XOPEN_SOURCE=500 \
|
||||||
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DSTATIC=static \
|
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DSTATIC=static \
|
||||||
@@ -68,7 +69,7 @@ C_CXX_FLAGS = -W -Wall -Werror -Wundef -Wno-comment -Wno-variadic-macros -Wpoin
|
|||||||
-DCS_PLATFORM=3 \
|
-DCS_PLATFORM=3 \
|
||||||
-ffunction-sections -fdata-sections
|
-ffunction-sections -fdata-sections
|
||||||
|
|
||||||
CFLAGS = -std=c99 $(C_CXX_FLAGS)
|
CFLAGS = -std=gnu99 $(C_CXX_FLAGS)
|
||||||
CXXFLAGS = -std=gnu++11 -fno-exceptions $(C_CXX_FLAGS)
|
CXXFLAGS = -std=gnu++11 -fno-exceptions $(C_CXX_FLAGS)
|
||||||
|
|
||||||
# linker flags used to generate the main object file
|
# linker flags used to generate the main object file
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "mongoose/mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
#ifdef RTOS_SDK
|
#ifdef RTOS_SDK
|
||||||
#include "esp_libc.h"
|
#include "esp_libc.h"
|
||||||
@@ -32,80 +44,3 @@ void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
|
|||||||
const size_t *msg_lens, uint8_t *digest) {
|
const size_t *msg_lens, uint8_t *digest) {
|
||||||
(void) sha1_vector(num_msgs, msgs, msg_lens, digest);
|
(void) sha1_vector(num_msgs, msgs, msg_lens, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
|
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
#include "mbedtls/sha256.h"
|
|
||||||
|
|
||||||
#define AES_PRIV_NR_POS (4 * 15)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Crypto functions in ROM/SDK.
|
|
||||||
* They come from wpa_supplicant, you can find them here https://w1.fi/cgit/
|
|
||||||
*
|
|
||||||
* Note that ROM version of the key setup function is older, does not take the
|
|
||||||
* number of bits argument and only supports AES-128. This prototype doesn't
|
|
||||||
* suit it, but since the difference is in the last aegument, it doesn't matter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void rijndaelKeySetupDec(void *ctx, const uint8_t *key, int bits);
|
|
||||||
extern int rijndaelKeySetupEnc(void *ctx, const uint8_t *key, int bits);
|
|
||||||
void aes_encrypt(void *ctx, const uint8_t *plain, uint8_t *crypt);
|
|
||||||
void aes_decrypt(void *ctx, const uint8_t *crypt, uint8_t *plain);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AES that comes with wpa_supplicant allocates its own AES context in
|
|
||||||
* aes_{encrypt,decrypt}_init. Ideally, we'd take that pointer and store it in
|
|
||||||
* our mbedtls_aes_context, but then a lot of space would be wasted.
|
|
||||||
* We do not call _init and go directly to key setup functions and poke number
|
|
||||||
* of rounds into the right place too. This is a bit hacky, but works fine.
|
|
||||||
* There is also a difference between older function in ROM and the one coming
|
|
||||||
* with SDK which is newer: the older one actually takes two arguments, not 3.
|
|
||||||
* But it doesn't matter, extra argument doesn't hurt and this works with both.
|
|
||||||
*/
|
|
||||||
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
|
|
||||||
unsigned int keybits) {
|
|
||||||
if (keybits != 128) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
|
||||||
((uint32_t *) ctx)[AES_PRIV_NR_POS] = 10;
|
|
||||||
rijndaelKeySetupEnc(ctx, key, 128);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
|
|
||||||
unsigned int keybits) {
|
|
||||||
if (keybits != 128) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
|
||||||
((uint32_t *) ctx)[AES_PRIV_NR_POS] = 10;
|
|
||||||
rijndaelKeySetupDec(ctx, key, 128);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
|
|
||||||
const unsigned char input[16],
|
|
||||||
unsigned char output[16]) {
|
|
||||||
aes_encrypt(ctx, input, output);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
|
|
||||||
const unsigned char input[16],
|
|
||||||
unsigned char output[16]) {
|
|
||||||
aes_decrypt(ctx, input, output);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* os_get_random uses hardware RNG, so it's cool. */
|
|
||||||
int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len) {
|
|
||||||
os_get_random(buf, len);
|
|
||||||
(void) ctx;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For CryptoAuthLib host crypto. */
|
|
||||||
int atcac_sw_sha2_256(const uint8_t *data, size_t data_size,
|
|
||||||
uint8_t digest[32]) {
|
|
||||||
mbedtls_sha256(data, data_size, digest, false /* is_224 */);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MG_ENABLE_SSL */
|
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_HW_WDT_REGISTER_H_
|
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_HW_WDT_REGISTER_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_MISSING_INCLUDES_H_
|
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_MISSING_INCLUDES_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_SSL_KRYPTON_H_
|
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_SSL_KRYPTON_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if ESP_UMM_ENABLE
|
#if ESP_UMM_ENABLE
|
||||||
|
|||||||
@@ -160,7 +160,8 @@ static uint8 calc_chksum(uint8 *start, uint8 *end) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UART_CLKDIV_26MHZ(B) (52000000 + B / 2) / B
|
#define UART_CLKDIV_80MHZ(B) (80000000 + B / 2) / B
|
||||||
|
#define UART_CLKDIV_52MHZ(B) (52000000 + B / 2) / B
|
||||||
|
|
||||||
// prevent this function being placed inline with main
|
// prevent this function being placed inline with main
|
||||||
// to keep main's stack size as small as possible
|
// to keep main's stack size as small as possible
|
||||||
@@ -182,10 +183,23 @@ uint32 NOINLINE find_image(void) {
|
|||||||
// delay to slow boot (help see messages when debugging)
|
// delay to slow boot (help see messages when debugging)
|
||||||
//ets_delay_us(2000000);
|
//ets_delay_us(2000000);
|
||||||
|
|
||||||
uart_div_modify(0, UART_CLKDIV_26MHZ(115200));
|
/*
|
||||||
|
* UART divider depends on the APB frequency. Cold boot starts with 52MHz APB,
|
||||||
|
* SDK configures PLL, sets it to 80 and it persists across soft reset
|
||||||
|
* so on soft reset a different divider should be used. What we really want to
|
||||||
|
* know is if the PLL is running but since that is completely undocumented
|
||||||
|
* we use CPU frequency bit as a workaround: mos sets CPU to 160 MHz on startup
|
||||||
|
* so we assume that if frequency is preserved, then it's soft reset, PLL is
|
||||||
|
* running and APB is at 80 MHz.
|
||||||
|
*/
|
||||||
|
if (READ_PERI_REG(0x3ff00014) & 1) {
|
||||||
|
uart_div_modify(0, UART_CLKDIV_80MHZ(115200));
|
||||||
|
} else {
|
||||||
|
uart_div_modify(0, UART_CLKDIV_52MHZ(115200));
|
||||||
|
}
|
||||||
ets_delay_us(1000);
|
ets_delay_us(1000);
|
||||||
|
|
||||||
ets_printf("\r\nrBoot v1.2.1 - richardaburton@gmail.com\r\n");
|
ets_printf("\r\nrBoot v1.2.1-cesanta1 - richardaburton@gmail.com\r\n");
|
||||||
|
|
||||||
// read rom header
|
// read rom header
|
||||||
SPIRead(0, header, sizeof(rom_header));
|
SPIRead(0, header, sizeof(rom_header));
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ LD := $(addprefix $(XTENSA_BINDIR)/,xtensa-lx106-elf-gcc)
|
|||||||
endif
|
endif
|
||||||
CC_WRAPPER ?=
|
CC_WRAPPER ?=
|
||||||
|
|
||||||
CFLAGS = -Os -O3 -Wpointer-arith -Wundef -Werror -Wl,-EL \
|
CFLAGS = -Os -Wpointer-arith -Wundef -Werror -Wl,-EL \
|
||||||
-fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals \
|
-fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals \
|
||||||
-D__ets__ -DIRAM='__attribute__((section(".fast.text")))' \
|
-D__ets__ -DIRAM='__attribute__((section(".fast.text")))' \
|
||||||
-DNOINSTR='__attribute__((no_instrument_function))' \
|
-DNOINSTR='__attribute__((no_instrument_function))' \
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ all: $(STUB_ELF)
|
|||||||
$(STUB_ELF): $(STUB) $(LIBS)
|
$(STUB_ELF): $(STUB) $(LIBS)
|
||||||
@echo " CC $^ -> $@"
|
@echo " CC $^ -> $@"
|
||||||
@[ -d $(BUILD_DIR) ] || mkdir $(BUILD_DIR)
|
@[ -d $(BUILD_DIR) ] || mkdir $(BUILD_DIR)
|
||||||
@docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||||
"cd /src/common/platforms/esp8266/stubs && \
|
"cd /src/common/platforms/esp8266/stubs && \
|
||||||
$(XT_CC) -std=c99 -Wall -Werror -Os -DESP8266 \
|
$(XT_CC) -std=c99 -Wall -Werror -Os -DESP8266 \
|
||||||
-mtext-section-literals -mlongcalls -nostdlib -fno-builtin \
|
-mtext-section-literals -mlongcalls -nostdlib -fno-builtin \
|
||||||
-I. -I/src/common/platforms/esp \
|
-I. -I/src/common/platforms/esp -I/src/common/platforms/esp8266 \
|
||||||
-I/opt/Espressif/ESP8266_SDK \
|
-I/opt/Espressif/ESP8266_SDK \
|
||||||
-Wl,-static -ffunction-sections -Wl,--gc-sections \
|
-Wl,-static -ffunction-sections -lgcc -Wl,--gc-sections \
|
||||||
-Tstub.ld $(CFLAGS) -o $@ $^"
|
-Tstub.ld $(CFLAGS) -o $@ $^"
|
||||||
|
|
||||||
wrap: $(STUB_JSON)
|
wrap: $(STUB_JSON)
|
||||||
|
|||||||
@@ -41,3 +41,4 @@ INCLUDE "eagle.rom.addr.v6.ld"
|
|||||||
PROVIDE(SPIFlashModeConfig = 0x40004568);
|
PROVIDE(SPIFlashModeConfig = 0x40004568);
|
||||||
PROVIDE(SPI_erase_sector = 0x400040c0);
|
PROVIDE(SPI_erase_sector = 0x400040c0);
|
||||||
PROVIDE(SPI_erase_block = 0x40004120);
|
PROVIDE(SPI_erase_block = 0x40004120);
|
||||||
|
PROVIDE(uart_div_modify = 0x400039d8);
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* Stub template.
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|||||||
@@ -1,14 +1,32 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
|
|
||||||
#define UART_CLKDIV_26MHZ(B) (52000000 + B / 2) / B
|
#define UART_CLKDIV_M (UART_CLKDIV_CNT << UART_CLKDIV_S)
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate) {
|
void uart_div_modify(uint8_t uart_no, uint32_t div);
|
||||||
uint32_t div = UART_CLKDIV_26MHZ(baud_rate);
|
|
||||||
WRITE_PERI_REG(UART_CLKDIV_REG(uart_no), div & 0xfffff);
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
|
uint32_t new_baud_rate) {
|
||||||
|
uint32_t uart_reg = READ_PERI_REG(UART_CLKDIV_REG(uart_no));
|
||||||
|
uint32_t uart_div = uart_reg & UART_CLKDIV_M;
|
||||||
|
uint32_t master_freq = uart_div * old_baud_rate;
|
||||||
|
uart_div_modify(uart_no, master_freq / new_baud_rate);
|
||||||
|
return uart_div;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_STUBS_UART_H_
|
#ifndef CS_COMMON_PLATFORMS_ESP8266_STUBS_UART_H_
|
||||||
@@ -8,9 +20,11 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate);
|
#include "uart_register.h"
|
||||||
|
|
||||||
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
|
uint32_t new_baud_rate);
|
||||||
|
|
||||||
#define REG_UART_BASE(i) (0x60000000 + (i) *0xf00)
|
|
||||||
#define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0)
|
#define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0)
|
||||||
#define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24)
|
#define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24)
|
||||||
#define UART_RX_TOUT_EN (BIT(31))
|
#define UART_RX_TOUT_EN (BIT(31))
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
# Analyzers output of firmware compiler with -DESP_ENABLE_MALLOC_TRACES
|
|
||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
allocs = {}
|
|
||||||
|
|
||||||
for l in sys.stdin:
|
|
||||||
m = re.match(r'(ca|ma|re|fr) (\S+)\s*(\S*)\s*(\S*)', l)
|
|
||||||
if not m: continue
|
|
||||||
op = m.group(1)
|
|
||||||
if op in ('ca', 'ma'):
|
|
||||||
allocs[m.group(2)] = long(m.group(3))
|
|
||||||
else:
|
|
||||||
if m.group(2) in allocs:
|
|
||||||
del allocs[m.group(2)]
|
|
||||||
if op == 're':
|
|
||||||
allocs[m.group(3)] = long(m.group(4))
|
|
||||||
|
|
||||||
for k, v in sorted(allocs.iteritems()):
|
|
||||||
print k, v
|
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_
|
#ifndef CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_
|
||||||
@@ -54,7 +66,6 @@ typedef int sock_t;
|
|||||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||||
struct mg_mgr;
|
struct mg_mgr;
|
||||||
struct mg_connection;
|
struct mg_connection;
|
||||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr);
|
|
||||||
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
||||||
int interval, int count);
|
int interval, int count);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||||
@@ -41,38 +53,27 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
|
|||||||
(struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data;
|
(struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data;
|
||||||
while (md->sig_queue_len > 0) {
|
while (md->sig_queue_len > 0) {
|
||||||
mgos_lock();
|
mgos_lock();
|
||||||
int sig = md->sig_queue[md->start_index].sig;
|
int i = md->start_index;
|
||||||
struct mg_connection *nc = md->sig_queue[md->start_index].nc;
|
int sig = md->sig_queue[i].sig;
|
||||||
|
struct mg_connection *nc = md->sig_queue[i].nc;
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
md->start_index = (md->start_index + 1) % MG_SIG_QUEUE_LEN;
|
md->start_index = (i + 1) % MG_SIG_QUEUE_LEN;
|
||||||
md->sig_queue_len--;
|
md->sig_queue_len--;
|
||||||
mgos_unlock();
|
mgos_unlock();
|
||||||
if (nc->iface == NULL || nc->mgr == NULL) continue;
|
if (nc->iface == NULL || nc->mgr == NULL) continue;
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case MG_SIG_CONNECT_RESULT: {
|
case MG_SIG_CONNECT_RESULT: {
|
||||||
#if MG_ENABLE_SSL
|
mg_if_connect_cb(nc, cs->err);
|
||||||
if (cs->err == 0 && (nc->flags & MG_F_SSL) &&
|
|
||||||
!(nc->flags & MG_F_SSL_HANDSHAKE_DONE)) {
|
|
||||||
mg_lwip_ssl_do_hs(nc);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
mg_if_connect_cb(nc, cs->err);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_SIG_CLOSE_CONN: {
|
case MG_SIG_CLOSE_CONN: {
|
||||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
|
||||||
mg_close_conn(nc);
|
mg_close_conn(nc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_SIG_RECV: {
|
case MG_SIG_RECV: {
|
||||||
cs->recv_pending = 0;
|
cs->recv_pending = 0;
|
||||||
if (nc->flags & MG_F_UDP) {
|
mg_if_can_recv_cb(nc);
|
||||||
mg_lwip_handle_recv_udp(nc);
|
mbuf_trim(&nc->recv_mbuf);
|
||||||
} else {
|
|
||||||
mg_lwip_handle_recv_tcp(nc);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_SIG_TOMBSTONE: {
|
case MG_SIG_TOMBSTONE: {
|
||||||
@@ -87,8 +88,13 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mg_lwip_if_init(struct mg_iface *iface) {
|
void mg_lwip_if_init(struct mg_iface *iface) {
|
||||||
LOG(LL_INFO, ("%p Mongoose init", iface));
|
LOG(LL_INFO, ("Mongoose %s, LwIP %u.%u.%u", MG_VERSION, LWIP_VERSION_MAJOR,
|
||||||
|
LWIP_VERSION_MINOR, LWIP_VERSION_REVISION));
|
||||||
iface->data = MG_CALLOC(1, sizeof(struct mg_ev_mgr_lwip_data));
|
iface->data = MG_CALLOC(1, sizeof(struct mg_ev_mgr_lwip_data));
|
||||||
|
#if !NO_SYS && !LWIP_TCPIP_CORE_LOCKING
|
||||||
|
sys_sem_new(&s_tcpip_call_lock_sem, 1);
|
||||||
|
sys_sem_new(&s_tcpip_call_sync_sem, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_lwip_if_free(struct mg_iface *iface) {
|
void mg_lwip_if_free(struct mg_iface *iface) {
|
||||||
@@ -126,46 +132,11 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
|
|||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
tmp = nc->next;
|
tmp = nc->next;
|
||||||
n++;
|
n++;
|
||||||
if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) ||
|
if (!mg_if_poll(nc, now)) continue;
|
||||||
((nc->flags & MG_F_SEND_AND_CLOSE) && (nc->flags & MG_F_UDP) &&
|
|
||||||
(nc->send_mbuf.len == 0))) {
|
|
||||||
mg_close_conn(nc);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mg_if_poll(nc, now);
|
|
||||||
mg_if_timer(nc, now);
|
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
if ((nc->flags & MG_F_SSL) && cs != NULL && cs->pcb.tcp != NULL &&
|
|
||||||
cs->pcb.tcp->state == ESTABLISHED) {
|
|
||||||
if (((nc->flags & MG_F_WANT_WRITE) ||
|
|
||||||
((nc->send_mbuf.len > 0) &&
|
|
||||||
(nc->flags & MG_F_SSL_HANDSHAKE_DONE))) &&
|
|
||||||
cs->pcb.tcp->snd_buf > 0) {
|
|
||||||
/* Can write more. */
|
|
||||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
|
||||||
if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_send(nc);
|
|
||||||
} else {
|
|
||||||
mg_lwip_ssl_do_hs(nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cs->rx_chain != NULL || (nc->flags & MG_F_WANT_READ)) {
|
|
||||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
|
||||||
if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_recv(nc);
|
|
||||||
} else {
|
|
||||||
mg_lwip_ssl_do_hs(nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif /* MG_ENABLE_SSL */
|
|
||||||
{
|
|
||||||
if (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING)) {
|
|
||||||
mg_lwip_send_more(nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nc->sock != INVALID_SOCKET &&
|
if (nc->sock != INVALID_SOCKET &&
|
||||||
!(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != NULL &&
|
!(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != NULL &&
|
||||||
cs->pcb.tcp->unsent != NULL) {
|
cs->pcb.tcp->unsent != NULL) {
|
||||||
tcpip_callback(tcp_output_tcpip, cs->pcb.tcp);
|
mg_lwip_netif_run_on_tcpip(tcp_output_tcpip, cs->pcb.tcp);
|
||||||
}
|
}
|
||||||
if (nc->ev_timer_time > 0) {
|
if (nc->ev_timer_time > 0) {
|
||||||
if (num_timers == 0 || nc->ev_timer_time < min_timer) {
|
if (num_timers == 0 || nc->ev_timer_time < min_timer) {
|
||||||
@@ -175,14 +146,17 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nc->sock != INVALID_SOCKET) {
|
if (nc->sock != INVALID_SOCKET) {
|
||||||
/* Try to consume data from cs->rx_chain */
|
if (mg_lwip_if_can_send(nc, cs)) {
|
||||||
mg_lwip_consume_rx_chain_tcp(nc);
|
mg_if_can_send_cb(nc);
|
||||||
|
mbuf_trim(&nc->send_mbuf);
|
||||||
/*
|
}
|
||||||
* If the connection is about to close, and rx_chain is finally empty,
|
if (cs->rx_chain != NULL) {
|
||||||
* send the MG_SIG_CLOSE_CONN signal
|
mg_if_can_recv_cb(nc);
|
||||||
*/
|
} else if (cs->draining_rx_chain) {
|
||||||
if (cs->draining_rx_chain && cs->rx_chain == NULL) {
|
/*
|
||||||
|
* If the connection is about to close, and rx_chain is finally empty,
|
||||||
|
* send the MG_SIG_CLOSE_CONN signal
|
||||||
|
*/
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,48 +170,4 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
|
|||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) {
|
|
||||||
struct mg_connection *nc;
|
|
||||||
double now;
|
|
||||||
double min_timer = 0;
|
|
||||||
int num_timers = 0;
|
|
||||||
mg_ev_mgr_lwip_process_signals(mgr);
|
|
||||||
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
if (nc->ev_timer_time > 0) {
|
|
||||||
if (num_timers == 0 || nc->ev_timer_time < min_timer) {
|
|
||||||
min_timer = nc->ev_timer_time;
|
|
||||||
}
|
|
||||||
num_timers++;
|
|
||||||
}
|
|
||||||
if (nc->send_mbuf.len > 0
|
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
|| (nc->flags & MG_F_WANT_WRITE)
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
int can_send = 0;
|
|
||||||
/* We have stuff to send, but can we? */
|
|
||||||
if (nc->flags & MG_F_UDP) {
|
|
||||||
/* UDP is always ready for sending. */
|
|
||||||
can_send = (cs->pcb.udp != NULL);
|
|
||||||
} else {
|
|
||||||
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
|
|
||||||
}
|
|
||||||
/* We want and can send, request a poll immediately. */
|
|
||||||
if (can_send) return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t timeout_ms = ~0;
|
|
||||||
now = mg_time();
|
|
||||||
if (num_timers > 0) {
|
|
||||||
/* If we have a timer that is past due, do a poll ASAP. */
|
|
||||||
if (min_timer < now) return 0;
|
|
||||||
double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */;
|
|
||||||
if (timer_timeout_ms < timeout_ms) {
|
|
||||||
timeout_ms = timer_timeout_ms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return timeout_ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
|
#endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
|
#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
|
||||||
@@ -12,7 +24,8 @@
|
|||||||
#include <lwip/tcp.h>
|
#include <lwip/tcp.h>
|
||||||
#include <lwip/tcpip.h>
|
#include <lwip/tcpip.h>
|
||||||
#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
|
#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
|
||||||
#include <lwip/priv/tcp_priv.h> /* For tcp_seg */
|
#include <lwip/priv/tcp_priv.h> /* For tcp_seg */
|
||||||
|
#include <lwip/priv/tcpip_priv.h> /* For tcpip_api_call */
|
||||||
#else
|
#else
|
||||||
#include <lwip/tcp_impl.h>
|
#include <lwip/tcp_impl.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -52,14 +65,36 @@
|
|||||||
#define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr
|
#define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NO_SYS
|
#if !NO_SYS
|
||||||
#define tcpip_callback(fn, arg) (fn)(arg)
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
typedef void (*tcpip_callback_fn)(void *arg);
|
/* With locking tcpip_api_call is just a function call wrapped in lock/unlock,
|
||||||
|
* so we can get away with just casting. */
|
||||||
|
void mg_lwip_netif_run_on_tcpip(void (*fn)(void *), void *arg) {
|
||||||
|
tcpip_api_call((tcpip_api_call_fn) fn, (struct tcpip_api_call_data *) arg);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static sys_sem_t s_tcpip_call_lock_sem = NULL;
|
||||||
|
static sys_sem_t s_tcpip_call_sync_sem = NULL;
|
||||||
|
struct mg_lwip_netif_tcpip_call_ctx {
|
||||||
|
void (*fn)(void *);
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
static void xxx_tcpip(void *arg) {
|
||||||
|
struct mg_lwip_netif_tcpip_call_ctx *ctx =
|
||||||
|
(struct mg_lwip_netif_tcpip_call_ctx *) arg;
|
||||||
|
ctx->fn(ctx->arg);
|
||||||
|
sys_sem_signal(&s_tcpip_call_sync_sem);
|
||||||
|
}
|
||||||
|
void mg_lwip_netif_run_on_tcpip(void (*fn)(void *), void *arg) {
|
||||||
|
struct mg_lwip_netif_tcpip_call_ctx ctx = {.fn = fn, .arg = arg};
|
||||||
|
sys_arch_sem_wait(&s_tcpip_call_lock_sem, 0);
|
||||||
|
tcpip_send_msg_wait_sem(xxx_tcpip, &ctx, &s_tcpip_call_sync_sem);
|
||||||
|
sys_sem_signal(&s_tcpip_call_lock_sem);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define mg_lwip_netif_run_on_tcpip(fn, arg) (fn)(arg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void mg_lwip_ssl_do_hs(struct mg_connection *nc);
|
|
||||||
void mg_lwip_ssl_send(struct mg_connection *nc);
|
|
||||||
void mg_lwip_ssl_recv(struct mg_connection *nc);
|
|
||||||
|
|
||||||
void mg_lwip_if_init(struct mg_iface *iface);
|
void mg_lwip_if_init(struct mg_iface *iface);
|
||||||
void mg_lwip_if_free(struct mg_iface *iface);
|
void mg_lwip_if_free(struct mg_iface *iface);
|
||||||
@@ -67,7 +102,8 @@ void mg_lwip_if_add_conn(struct mg_connection *nc);
|
|||||||
void mg_lwip_if_remove_conn(struct mg_connection *nc);
|
void mg_lwip_if_remove_conn(struct mg_connection *nc);
|
||||||
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms);
|
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms);
|
||||||
|
|
||||||
#if defined(RTOS_SDK) || defined(ESP_PLATFORM)
|
// If compiling for Mongoose OS.
|
||||||
|
#ifdef MGOS
|
||||||
extern void mgos_lock();
|
extern void mgos_lock();
|
||||||
extern void mgos_unlock();
|
extern void mgos_unlock();
|
||||||
#else
|
#else
|
||||||
@@ -118,7 +154,7 @@ static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
|||||||
static void mg_lwip_tcp_error_cb(void *arg, err_t err) {
|
static void mg_lwip_tcp_error_cb(void *arg, err_t err) {
|
||||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||||
DBG(("%p conn error %d", nc, err));
|
DBG(("%p conn error %d", nc, err));
|
||||||
if (nc == NULL) return;
|
if (nc == NULL || (nc->flags & MG_F_CLOSE_IMMEDIATELY)) return;
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
cs->pcb.tcp = NULL; /* Has already been deallocated */
|
cs->pcb.tcp = NULL; /* Has already been deallocated */
|
||||||
if (nc->flags & MG_F_CONNECTING) {
|
if (nc->flags & MG_F_CONNECTING) {
|
||||||
@@ -132,10 +168,12 @@ static void mg_lwip_tcp_error_cb(void *arg, err_t err) {
|
|||||||
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
||||||
struct pbuf *p, err_t err) {
|
struct pbuf *p, err_t err) {
|
||||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||||
DBG(("%p %p %u %d", nc, tpcb, (p != NULL ? p->tot_len : 0), err));
|
struct mg_lwip_conn_state *cs =
|
||||||
|
(nc ? (struct mg_lwip_conn_state *) nc->sock : NULL);
|
||||||
|
DBG(("%p %p %p %p %u %d", nc, cs, tpcb, p, (p != NULL ? p->tot_len : 0),
|
||||||
|
err));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
if (nc != NULL && !(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
|
if (nc != NULL && !(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
if (cs->rx_chain != NULL) {
|
if (cs->rx_chain != NULL) {
|
||||||
/*
|
/*
|
||||||
* rx_chain still contains non-consumed data, don't close the
|
* rx_chain still contains non-consumed data, don't close the
|
||||||
@@ -153,7 +191,6 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
|||||||
tcp_abort(tpcb);
|
tcp_abort(tpcb);
|
||||||
return ERR_ARG;
|
return ERR_ARG;
|
||||||
}
|
}
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
/*
|
/*
|
||||||
* If we get a chain of more than one segment at once, we need to bump
|
* If we get a chain of more than one segment at once, we need to bump
|
||||||
* refcount on the subsequent bufs to make them independent.
|
* refcount on the subsequent bufs to make them independent.
|
||||||
@@ -168,7 +205,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
|||||||
} else if (pbuf_clen(cs->rx_chain) >= 4) {
|
} else if (pbuf_clen(cs->rx_chain) >= 4) {
|
||||||
/* ESP SDK has a limited pool of 5 pbufs. We must not hog them all or RX
|
/* ESP SDK has a limited pool of 5 pbufs. We must not hog them all or RX
|
||||||
* will be completely blocked. We already have at least 4 in the chain,
|
* will be completely blocked. We already have at least 4 in the chain,
|
||||||
* this one is, so we have to make a copy and release this one. */
|
* this one is the last, so we have to make a copy and release this one. */
|
||||||
struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||||
if (np != NULL) {
|
if (np != NULL) {
|
||||||
pbuf_copy(np, p);
|
pbuf_copy(np, p);
|
||||||
@@ -176,58 +213,10 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
|||||||
p = np;
|
p = np;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mgos_unlock();
|
|
||||||
mg_lwip_recv_common(nc, p);
|
mg_lwip_recv_common(nc, p);
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mg_lwip_consume_rx_chain_tcp(struct mg_connection *nc) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
if (cs->rx_chain == NULL) return;
|
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
if (nc->flags & MG_F_SSL) {
|
|
||||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
|
||||||
mg_lwip_ssl_recv(nc);
|
|
||||||
} else {
|
|
||||||
mg_lwip_ssl_do_hs(nc);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mgos_lock();
|
|
||||||
while (cs->rx_chain != NULL && nc->recv_mbuf.len < nc->recv_mbuf_limit) {
|
|
||||||
struct pbuf *seg = cs->rx_chain;
|
|
||||||
|
|
||||||
size_t seg_len = (seg->len - cs->rx_offset);
|
|
||||||
size_t buf_avail = (nc->recv_mbuf_limit - nc->recv_mbuf.len);
|
|
||||||
size_t len = MIN(seg_len, buf_avail);
|
|
||||||
|
|
||||||
char *data = (char *) MG_MALLOC(len);
|
|
||||||
if (data == NULL) {
|
|
||||||
mgos_unlock();
|
|
||||||
DBG(("OOM"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pbuf_copy_partial(seg, data, len, cs->rx_offset);
|
|
||||||
cs->rx_offset += len;
|
|
||||||
if (cs->rx_offset == cs->rx_chain->len) {
|
|
||||||
cs->rx_chain = pbuf_dechain(cs->rx_chain);
|
|
||||||
pbuf_free(seg);
|
|
||||||
cs->rx_offset = 0;
|
|
||||||
}
|
|
||||||
mgos_unlock();
|
|
||||||
mg_if_recv_tcp_cb(nc, data, len, 1 /* own */);
|
|
||||||
mgos_lock();
|
|
||||||
}
|
|
||||||
mgos_unlock();
|
mgos_unlock();
|
||||||
}
|
(void) err;
|
||||||
|
return ERR_OK;
|
||||||
static void mg_lwip_handle_recv_tcp(struct mg_connection *nc) {
|
|
||||||
mg_lwip_consume_rx_chain_tcp(nc);
|
|
||||||
|
|
||||||
if (nc->send_mbuf.len > 0) {
|
|
||||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
|
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
|
||||||
@@ -239,6 +228,10 @@ static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
|
|||||||
nc->send_mbuf.len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
|
nc->send_mbuf.len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||||
}
|
}
|
||||||
|
if (nc->send_mbuf.len > 0 || (nc->flags & MG_F_WANT_WRITE)) {
|
||||||
|
mg_lwip_mgr_schedule_poll(nc->mgr);
|
||||||
|
}
|
||||||
|
(void) num_sent;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +272,7 @@ static void mg_lwip_if_connect_tcp_tcpip(void *arg) {
|
|||||||
void mg_lwip_if_connect_tcp(struct mg_connection *nc,
|
void mg_lwip_if_connect_tcp(struct mg_connection *nc,
|
||||||
const union socket_address *sa) {
|
const union socket_address *sa) {
|
||||||
struct mg_lwip_if_connect_tcp_ctx ctx = {.nc = nc, .sa = sa};
|
struct mg_lwip_if_connect_tcp_ctx ctx = {.nc = nc, .sa = sa};
|
||||||
tcpip_callback(mg_lwip_if_connect_tcp_tcpip, &ctx);
|
mg_lwip_netif_run_on_tcpip(mg_lwip_if_connect_tcp_tcpip, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -313,13 +306,14 @@ static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
/* Logic in the recv handler requires that there be exactly one data pbuf. */
|
/* Logic in the recv handler requires that there be exactly one data pbuf. */
|
||||||
p = pbuf_coalesce(p, PBUF_RAW);
|
p = pbuf_coalesce(p, PBUF_RAW);
|
||||||
pbuf_chain(sap, p);
|
pbuf_chain(sap, p);
|
||||||
|
mgos_lock();
|
||||||
mg_lwip_recv_common(nc, sap);
|
mg_lwip_recv_common(nc, sap);
|
||||||
|
mgos_unlock();
|
||||||
(void) pcb;
|
(void) pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p) {
|
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p) {
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
mgos_lock();
|
|
||||||
if (cs->rx_chain == NULL) {
|
if (cs->rx_chain == NULL) {
|
||||||
cs->rx_chain = p;
|
cs->rx_chain = p;
|
||||||
} else {
|
} else {
|
||||||
@@ -329,32 +323,30 @@ static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p) {
|
|||||||
cs->recv_pending = 1;
|
cs->recv_pending = 1;
|
||||||
mg_lwip_post_signal(MG_SIG_RECV, nc);
|
mg_lwip_post_signal(MG_SIG_RECV, nc);
|
||||||
}
|
}
|
||||||
mgos_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_lwip_handle_recv_udp(struct mg_connection *nc) {
|
static int mg_lwip_if_udp_recv(struct mg_connection *nc, void *buf, size_t len,
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
union socket_address *sa, size_t *sa_len) {
|
||||||
/*
|
/*
|
||||||
* For UDP, RX chain consists of interleaved address and packet bufs:
|
* For UDP, RX chain consists of interleaved address and packet bufs:
|
||||||
* Address pbuf followed by exactly one data pbuf (recv_cb took care of that).
|
* Address pbuf followed by exactly one data pbuf (recv_cb took care of that).
|
||||||
*/
|
*/
|
||||||
while (cs->rx_chain != NULL) {
|
int res = 0;
|
||||||
struct pbuf *sap = cs->rx_chain;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
struct pbuf *p = sap->next;
|
if (nc->sock == INVALID_SOCKET) return -1;
|
||||||
cs->rx_chain = pbuf_dechain(p);
|
mgos_lock();
|
||||||
size_t data_len = p->len;
|
if (cs->rx_chain != NULL) {
|
||||||
char *data = (char *) MG_MALLOC(data_len);
|
struct pbuf *ap = cs->rx_chain;
|
||||||
if (data != NULL) {
|
struct pbuf *dp = ap->next;
|
||||||
pbuf_copy_partial(p, data, data_len, 0);
|
cs->rx_chain = pbuf_dechain(dp);
|
||||||
pbuf_free(p);
|
res = MIN(dp->len, len);
|
||||||
mg_if_recv_udp_cb(nc, data, data_len,
|
pbuf_copy_partial(dp, buf, res, 0);
|
||||||
(union socket_address *) sap->payload, sap->len);
|
pbuf_free(dp);
|
||||||
pbuf_free(sap);
|
pbuf_copy_partial(ap, sa, MIN(*sa_len, ap->len), 0);
|
||||||
} else {
|
pbuf_free(ap);
|
||||||
pbuf_free(p);
|
|
||||||
pbuf_free(sap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mgos_unlock();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_lwip_if_connect_udp_tcpip(void *arg) {
|
static void mg_lwip_if_connect_udp_tcpip(void *arg) {
|
||||||
@@ -373,14 +365,7 @@ static void mg_lwip_if_connect_udp_tcpip(void *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mg_lwip_if_connect_udp(struct mg_connection *nc) {
|
void mg_lwip_if_connect_udp(struct mg_connection *nc) {
|
||||||
tcpip_callback(mg_lwip_if_connect_udp_tcpip, nc);
|
mg_lwip_netif_run_on_tcpip(mg_lwip_if_connect_udp_tcpip, nc);
|
||||||
}
|
|
||||||
|
|
||||||
void mg_lwip_accept_conn(struct mg_connection *nc, struct tcp_pcb *tpcb) {
|
|
||||||
union socket_address sa;
|
|
||||||
SET_ADDR(&sa, &tpcb->remote_ip);
|
|
||||||
sa.sin.sin_port = htons(tpcb->remote_port);
|
|
||||||
mg_if_accept_tcp_cb(nc, &sa, sizeof(sa.sin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcp_close_tcpip(void *arg) {
|
static void tcp_close_tcpip(void *arg) {
|
||||||
@@ -390,17 +375,11 @@ static void tcp_close_tcpip(void *arg) {
|
|||||||
void mg_lwip_handle_accept(struct mg_connection *nc) {
|
void mg_lwip_handle_accept(struct mg_connection *nc) {
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
if (cs->pcb.tcp == NULL) return;
|
if (cs->pcb.tcp == NULL) return;
|
||||||
#if MG_ENABLE_SSL
|
union socket_address sa;
|
||||||
if (cs->lc->flags & MG_F_SSL) {
|
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||||
if (mg_ssl_if_conn_accept(nc, cs->lc) != MG_SSL_OK) {
|
SET_ADDR(&sa, &tpcb->remote_ip);
|
||||||
LOG(LL_ERROR, ("SSL error"));
|
sa.sin.sin_port = htons(tpcb->remote_port);
|
||||||
tcpip_callback(tcp_close_tcpip, cs->pcb.tcp);
|
mg_if_accept_tcp_cb(nc, &sa, sizeof(sa.sin));
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
mg_lwip_accept_conn(nc, cs->pcb.tcp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err) {
|
static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err) {
|
||||||
@@ -472,7 +451,7 @@ static void mg_lwip_if_listen_tcp_tcpip(void *arg) {
|
|||||||
|
|
||||||
int mg_lwip_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
|
int mg_lwip_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
|
||||||
struct mg_lwip_if_listen_ctx ctx = {.nc = nc, .sa = sa};
|
struct mg_lwip_if_listen_ctx ctx = {.nc = nc, .sa = sa};
|
||||||
tcpip_callback(mg_lwip_if_listen_tcp_tcpip, &ctx);
|
mg_lwip_netif_run_on_tcpip(mg_lwip_if_listen_tcp_tcpip, &ctx);
|
||||||
return ctx.ret;
|
return ctx.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +477,7 @@ static void mg_lwip_if_listen_udp_tcpip(void *arg) {
|
|||||||
|
|
||||||
int mg_lwip_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
|
int mg_lwip_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
|
||||||
struct mg_lwip_if_listen_ctx ctx = {.nc = nc, .sa = sa};
|
struct mg_lwip_if_listen_ctx ctx = {.nc = nc, .sa = sa};
|
||||||
tcpip_callback(mg_lwip_if_listen_udp_tcpip, &ctx);
|
mg_lwip_netif_run_on_tcpip(mg_lwip_if_listen_udp_tcpip, &ctx);
|
||||||
return ctx.ret;
|
return ctx.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +502,7 @@ static void mg_lwip_tcp_write_tcpip(void *arg) {
|
|||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
DBG(("%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen,
|
DBG(("%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen,
|
||||||
tpcb->unsent, tpcb->unacked));
|
tpcb->unsent, tpcb->unacked));
|
||||||
tcpip_callback(tcp_output_tcpip, tpcb);
|
mg_lwip_netif_run_on_tcpip(tcp_output_tcpip, tpcb);
|
||||||
ctx->ret = 0;
|
ctx->ret = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -555,17 +534,18 @@ static void mg_lwip_tcp_write_tcpip(void *arg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx->ret = len;
|
ctx->ret = len;
|
||||||
|
(void) unsent;
|
||||||
|
(void) unacked;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_lwip_tcp_write(struct mg_connection *nc, const void *data,
|
int mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) {
|
||||||
uint16_t len) {
|
struct mg_lwip_tcp_write_ctx ctx = {.nc = nc, .data = buf, .len = len};
|
||||||
struct mg_lwip_tcp_write_ctx ctx = {.nc = nc, .data = data, .len = len};
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
|
if (nc->sock == INVALID_SOCKET) return -1;
|
||||||
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||||
if (tpcb == NULL) {
|
if (tpcb == NULL) return -1;
|
||||||
return -1;
|
if (tpcb->snd_buf <= 0) return 0;
|
||||||
}
|
mg_lwip_netif_run_on_tcpip(mg_lwip_tcp_write_tcpip, &ctx);
|
||||||
tcpip_callback(mg_lwip_tcp_write_tcpip, &ctx);
|
|
||||||
return ctx.ret;
|
return ctx.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,18 +562,10 @@ static void udp_sendto_tcpip(void *arg) {
|
|||||||
ctx->ret = udp_sendto(ctx->upcb, ctx->p, ctx->ip, ctx->port);
|
ctx->ret = udp_sendto(ctx->upcb, ctx->p, ctx->ip, ctx->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_lwip_udp_send(struct mg_connection *nc, const void *data,
|
static int mg_lwip_if_udp_send(struct mg_connection *nc, const void *data,
|
||||||
uint16_t len) {
|
size_t len) {
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
if (cs->pcb.udp == NULL) {
|
if (nc->sock == INVALID_SOCKET || cs->pcb.udp == NULL) return -1;
|
||||||
/*
|
|
||||||
* In case of UDP, this usually means, what
|
|
||||||
* async DNS resolve is still in progress and connection
|
|
||||||
* is not ready yet
|
|
||||||
*/
|
|
||||||
DBG(("%p socket is not connected", nc));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
struct udp_pcb *upcb = cs->pcb.udp;
|
struct udp_pcb *upcb = cs->pcb.udp;
|
||||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
|
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
|
||||||
#if defined(LWIP_IPV4) && LWIP_IPV4 && defined(LWIP_IPV6) && LWIP_IPV6
|
#if defined(LWIP_IPV4) && LWIP_IPV4 && defined(LWIP_IPV6) && LWIP_IPV6
|
||||||
@@ -602,46 +574,32 @@ static int mg_lwip_udp_send(struct mg_connection *nc, const void *data,
|
|||||||
ip_addr_t ip = {.addr = nc->sa.sin.sin_addr.s_addr};
|
ip_addr_t ip = {.addr = nc->sa.sin.sin_addr.s_addr};
|
||||||
#endif
|
#endif
|
||||||
u16_t port = ntohs(nc->sa.sin.sin_port);
|
u16_t port = ntohs(nc->sa.sin.sin_port);
|
||||||
if (p == NULL) {
|
if (p == NULL) return 0;
|
||||||
DBG(("OOM"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(p->payload, data, len);
|
memcpy(p->payload, data, len);
|
||||||
struct udp_sendto_ctx ctx = {.upcb = upcb, .p = p, .ip = &ip, .port = port};
|
struct udp_sendto_ctx ctx = {.upcb = upcb, .p = p, .ip = &ip, .port = port};
|
||||||
tcpip_callback(udp_sendto_tcpip, &ctx);
|
mg_lwip_netif_run_on_tcpip(udp_sendto_tcpip, &ctx);
|
||||||
cs->err = ctx.ret;
|
cs->err = ctx.ret;
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return (cs->err == ERR_OK ? len : -1);
|
return (cs->err == ERR_OK ? (int) len : -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_lwip_send_more(struct mg_connection *nc) {
|
static int mg_lwip_if_can_send(struct mg_connection *nc,
|
||||||
int num_sent = 0;
|
struct mg_lwip_conn_state *cs) {
|
||||||
if (nc->sock == INVALID_SOCKET) return;
|
int can_send = 0;
|
||||||
if (nc->flags & MG_F_UDP) {
|
if (nc->send_mbuf.len > 0 || (nc->flags & MG_F_WANT_WRITE)) {
|
||||||
num_sent = mg_lwip_udp_send(nc, nc->send_mbuf.buf, nc->send_mbuf.len);
|
/* We have stuff to send, but can we? */
|
||||||
DBG(("%p mg_lwip_udp_send %u = %d", nc, nc->send_mbuf.len, num_sent));
|
if (nc->flags & MG_F_UDP) {
|
||||||
} else {
|
/* UDP is always ready for sending. */
|
||||||
num_sent = mg_lwip_tcp_write(nc, nc->send_mbuf.buf, nc->send_mbuf.len);
|
can_send = (cs->pcb.udp != NULL);
|
||||||
DBG(("%p mg_lwip_tcp_write %u = %d", nc, nc->send_mbuf.len, num_sent));
|
} else {
|
||||||
|
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
|
||||||
|
/* See comment above. */
|
||||||
|
#if CS_PLATFORM == CS_P_ESP8266
|
||||||
|
if (cs->pcb.tcp->unacked != NULL) can_send = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (num_sent == 0) return;
|
return can_send;
|
||||||
if (num_sent > 0) {
|
|
||||||
mg_if_sent_cb(nc, num_sent);
|
|
||||||
} else {
|
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf,
|
|
||||||
size_t len) {
|
|
||||||
mbuf_append(&nc->send_mbuf, buf, len);
|
|
||||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_lwip_if_udp_send(struct mg_connection *nc, const void *buf,
|
|
||||||
size_t len) {
|
|
||||||
mbuf_append(&nc->send_mbuf, buf, len);
|
|
||||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tcp_recved_ctx {
|
struct tcp_recved_ctx {
|
||||||
@@ -651,30 +609,38 @@ struct tcp_recved_ctx {
|
|||||||
|
|
||||||
void tcp_recved_tcpip(void *arg) {
|
void tcp_recved_tcpip(void *arg) {
|
||||||
struct tcp_recved_ctx *ctx = (struct tcp_recved_ctx *) arg;
|
struct tcp_recved_ctx *ctx = (struct tcp_recved_ctx *) arg;
|
||||||
tcp_recved(ctx->tpcb, ctx->len);
|
if (ctx->tpcb != NULL) tcp_recved(ctx->tpcb, ctx->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_lwip_if_recved(struct mg_connection *nc, size_t len) {
|
static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf,
|
||||||
if (nc->flags & MG_F_UDP) return;
|
size_t len) {
|
||||||
|
int res = 0;
|
||||||
|
char *bufp = buf;
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||||
if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) {
|
if (nc->sock == INVALID_SOCKET) return -1;
|
||||||
DBG(("%p invalid socket", nc));
|
mgos_lock();
|
||||||
return;
|
while (cs->rx_chain != NULL && len > 0) {
|
||||||
|
struct pbuf *seg = cs->rx_chain;
|
||||||
|
size_t seg_len = (seg->len - cs->rx_offset);
|
||||||
|
size_t copy_len = MIN(len, seg_len);
|
||||||
|
|
||||||
|
pbuf_copy_partial(seg, bufp, copy_len, cs->rx_offset);
|
||||||
|
len -= copy_len;
|
||||||
|
res += copy_len;
|
||||||
|
bufp += copy_len;
|
||||||
|
cs->rx_offset += copy_len;
|
||||||
|
if (cs->rx_offset == cs->rx_chain->len) {
|
||||||
|
cs->rx_chain = pbuf_dechain(cs->rx_chain);
|
||||||
|
pbuf_free(seg);
|
||||||
|
cs->rx_offset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DBG(("%p %p %u %u", nc, cs->pcb.tcp, len,
|
mgos_unlock();
|
||||||
(cs->rx_chain ? cs->rx_chain->tot_len : 0)));
|
if (res > 0) {
|
||||||
struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = len};
|
struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = res};
|
||||||
#if MG_ENABLE_SSL
|
mg_lwip_netif_run_on_tcpip(tcp_recved_tcpip, &ctx);
|
||||||
if (!(nc->flags & MG_F_SSL)) {
|
|
||||||
tcpip_callback(tcp_recved_tcpip, &ctx);
|
|
||||||
} else {
|
|
||||||
/* Currently SSL acknowledges data immediately.
|
|
||||||
* TODO(rojer): Find a way to propagate mg_lwip_if_recved. */
|
|
||||||
}
|
}
|
||||||
#else
|
return res;
|
||||||
tcpip_callback(tcp_recved_tcpip, &ctx);
|
|
||||||
#endif
|
|
||||||
mbuf_trim(&nc->recv_mbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_lwip_if_create_conn(struct mg_connection *nc) {
|
int mg_lwip_if_create_conn(struct mg_connection *nc) {
|
||||||
@@ -699,7 +665,7 @@ void mg_lwip_if_destroy_conn(struct mg_connection *nc) {
|
|||||||
tcp_arg(tpcb, NULL);
|
tcp_arg(tpcb, NULL);
|
||||||
DBG(("%p tcp_close %p", nc, tpcb));
|
DBG(("%p tcp_close %p", nc, tpcb));
|
||||||
tcp_arg(tpcb, NULL);
|
tcp_arg(tpcb, NULL);
|
||||||
tcpip_callback(tcp_close_tcpip, tpcb);
|
mg_lwip_netif_run_on_tcpip(tcp_close_tcpip, tpcb);
|
||||||
}
|
}
|
||||||
while (cs->rx_chain != NULL) {
|
while (cs->rx_chain != NULL) {
|
||||||
struct pbuf *seg = cs->rx_chain;
|
struct pbuf *seg = cs->rx_chain;
|
||||||
@@ -713,7 +679,7 @@ void mg_lwip_if_destroy_conn(struct mg_connection *nc) {
|
|||||||
struct udp_pcb *upcb = cs->pcb.udp;
|
struct udp_pcb *upcb = cs->pcb.udp;
|
||||||
if (upcb != NULL) {
|
if (upcb != NULL) {
|
||||||
DBG(("%p udp_remove %p", nc, upcb));
|
DBG(("%p udp_remove %p", nc, upcb));
|
||||||
tcpip_callback(udp_remove_tcpip, upcb);
|
mg_lwip_netif_run_on_tcpip(udp_remove_tcpip, upcb);
|
||||||
}
|
}
|
||||||
memset(cs, 0, sizeof(*cs));
|
memset(cs, 0, sizeof(*cs));
|
||||||
MG_FREE(cs);
|
MG_FREE(cs);
|
||||||
@@ -763,7 +729,8 @@ void mg_lwip_if_sock_set(struct mg_connection *nc, sock_t sock) {
|
|||||||
mg_lwip_if_connect_udp, \
|
mg_lwip_if_connect_udp, \
|
||||||
mg_lwip_if_tcp_send, \
|
mg_lwip_if_tcp_send, \
|
||||||
mg_lwip_if_udp_send, \
|
mg_lwip_if_udp_send, \
|
||||||
mg_lwip_if_recved, \
|
mg_lwip_if_tcp_recv, \
|
||||||
|
mg_lwip_if_udp_recv, \
|
||||||
mg_lwip_if_create_conn, \
|
mg_lwip_if_create_conn, \
|
||||||
mg_lwip_if_destroy_conn, \
|
mg_lwip_if_destroy_conn, \
|
||||||
mg_lwip_if_sock_set, \
|
mg_lwip_if_sock_set, \
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_
|
#ifndef CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_
|
||||||
@@ -30,9 +42,9 @@ struct mg_lwip_conn_state {
|
|||||||
/* Last SSL write size, for retries. */
|
/* Last SSL write size, for retries. */
|
||||||
int last_ssl_write_size;
|
int last_ssl_write_size;
|
||||||
/* Whether MG_SIG_RECV is already pending for this connection */
|
/* Whether MG_SIG_RECV is already pending for this connection */
|
||||||
int recv_pending : 1;
|
int recv_pending;
|
||||||
/* Whether the connection is about to close, just `rx_chain` needs to drain */
|
/* Whether the connection is about to close, just `rx_chain` needs to drain */
|
||||||
int draining_rx_chain : 1;
|
int draining_rx_chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mg_sig_type {
|
enum mg_sig_type {
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if MG_ENABLE_SSL && MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
|
||||||
|
|
||||||
#include "common/mg_mem.h"
|
|
||||||
#include "common/cs_dbg.h"
|
|
||||||
|
|
||||||
#include <lwip/pbuf.h>
|
|
||||||
#include <lwip/tcp.h>
|
|
||||||
|
|
||||||
#ifndef MG_LWIP_SSL_IO_SIZE
|
|
||||||
#define MG_LWIP_SSL_IO_SIZE 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void mg_lwip_ssl_do_hs(struct mg_connection *nc) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
int server_side = (nc->listener != NULL);
|
|
||||||
enum mg_ssl_if_result res;
|
|
||||||
if (nc->flags & MG_F_CLOSE_IMMEDIATELY) return;
|
|
||||||
res = mg_ssl_if_handshake(nc);
|
|
||||||
DBG(("%p %lu %d %d", nc, nc->flags, server_side, res));
|
|
||||||
if (res != MG_SSL_OK) {
|
|
||||||
if (res == MG_SSL_WANT_WRITE) {
|
|
||||||
nc->flags |= MG_F_WANT_WRITE;
|
|
||||||
cs->err = 0;
|
|
||||||
} else if (res == MG_SSL_WANT_READ) {
|
|
||||||
/*
|
|
||||||
* Nothing to do in particular, we are callback-driven.
|
|
||||||
* What we definitely do not need anymore is SSL reading (nothing left).
|
|
||||||
*/
|
|
||||||
nc->flags &= ~MG_F_WANT_READ;
|
|
||||||
cs->err = 0;
|
|
||||||
} else {
|
|
||||||
cs->err = res;
|
|
||||||
if (server_side) {
|
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
|
||||||
} else {
|
|
||||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cs->err = 0;
|
|
||||||
nc->flags &= ~MG_F_WANT_WRITE;
|
|
||||||
/*
|
|
||||||
* Handshake is done. Schedule a read immediately to consume app data
|
|
||||||
* which may already be waiting.
|
|
||||||
*/
|
|
||||||
nc->flags |= (MG_F_SSL_HANDSHAKE_DONE | MG_F_WANT_READ);
|
|
||||||
if (server_side) {
|
|
||||||
mg_lwip_accept_conn(nc, cs->pcb.tcp);
|
|
||||||
} else {
|
|
||||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_lwip_ssl_send(struct mg_connection *nc) {
|
|
||||||
if (nc->sock == INVALID_SOCKET) {
|
|
||||||
DBG(("%p invalid socket", nc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
/* It's ok if the buffer is empty. Return value of 0 may also be valid. */
|
|
||||||
int len = cs->last_ssl_write_size;
|
|
||||||
if (len == 0) {
|
|
||||||
len = MIN(MG_LWIP_SSL_IO_SIZE, nc->send_mbuf.len);
|
|
||||||
}
|
|
||||||
int ret = mg_ssl_if_write(nc, nc->send_mbuf.buf, len);
|
|
||||||
DBG(("%p SSL_write %u = %d", nc, len, ret));
|
|
||||||
if (ret > 0) {
|
|
||||||
mg_if_sent_cb(nc, ret);
|
|
||||||
cs->last_ssl_write_size = 0;
|
|
||||||
} else if (ret < 0) {
|
|
||||||
/* This is tricky. We must remember the exact data we were sending to retry
|
|
||||||
* exactly the same send next time. */
|
|
||||||
cs->last_ssl_write_size = len;
|
|
||||||
}
|
|
||||||
if (ret == len) {
|
|
||||||
nc->flags &= ~MG_F_WANT_WRITE;
|
|
||||||
} else if (ret == MG_SSL_WANT_WRITE) {
|
|
||||||
nc->flags |= MG_F_WANT_WRITE;
|
|
||||||
} else {
|
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_lwip_ssl_recv(struct mg_connection *nc) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
/* Don't deliver data before connect callback */
|
|
||||||
if (nc->flags & MG_F_CONNECTING) return;
|
|
||||||
while (nc->recv_mbuf.len < nc->recv_mbuf_limit) {
|
|
||||||
char *buf = (char *) MG_MALLOC(MG_LWIP_SSL_IO_SIZE);
|
|
||||||
if (buf == NULL) return;
|
|
||||||
int ret = mg_ssl_if_read(nc, buf, MG_LWIP_SSL_IO_SIZE);
|
|
||||||
DBG(("%p %p SSL_read %u = %d", nc, cs->rx_chain, MG_LWIP_SSL_IO_SIZE, ret));
|
|
||||||
if (ret <= 0) {
|
|
||||||
MG_FREE(buf);
|
|
||||||
if (ret == MG_SSL_WANT_WRITE) {
|
|
||||||
nc->flags |= MG_F_WANT_WRITE;
|
|
||||||
return;
|
|
||||||
} else if (ret == MG_SSL_WANT_READ) {
|
|
||||||
/*
|
|
||||||
* Nothing to do in particular, we are callback-driven.
|
|
||||||
* What we definitely do not need anymore is SSL reading (nothing left).
|
|
||||||
*/
|
|
||||||
nc->flags &= ~MG_F_WANT_READ;
|
|
||||||
cs->err = 0;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mg_if_recv_tcp_cb(nc, buf, ret, 1 /* own */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KR_VERSION
|
|
||||||
|
|
||||||
ssize_t kr_send(int fd, const void *buf, size_t len) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd;
|
|
||||||
int ret = mg_lwip_tcp_write(cs->nc, buf, len);
|
|
||||||
DBG(("%p mg_lwip_tcp_write %u = %d", cs->nc, len, ret));
|
|
||||||
if (ret == 0) ret = KR_IO_WOULDBLOCK;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t kr_recv(int fd, void *buf, size_t len) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd;
|
|
||||||
struct pbuf *seg = cs->rx_chain;
|
|
||||||
if (seg == NULL) {
|
|
||||||
DBG(("%u - nothing to read", len));
|
|
||||||
return KR_IO_WOULDBLOCK;
|
|
||||||
}
|
|
||||||
size_t seg_len = (seg->len - cs->rx_offset);
|
|
||||||
DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
|
|
||||||
len = MIN(len, seg_len);
|
|
||||||
pbuf_copy_partial(seg, buf, len, cs->rx_offset);
|
|
||||||
cs->rx_offset += len;
|
|
||||||
tcp_recved(cs->pcb.tcp, len);
|
|
||||||
if (cs->rx_offset == cs->rx_chain->len) {
|
|
||||||
cs->rx_chain = pbuf_dechain(cs->rx_chain);
|
|
||||||
pbuf_free(seg);
|
|
||||||
cs->rx_offset = 0;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif MG_SSL_IF == MG_SSL_IF_MBEDTLS
|
|
||||||
|
|
||||||
int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len) {
|
|
||||||
struct mg_connection *nc = (struct mg_connection *) ctx;
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
int ret = mg_lwip_tcp_write(cs->nc, buf, len);
|
|
||||||
if (ret == 0) ret = MBEDTLS_ERR_SSL_WANT_WRITE;
|
|
||||||
LOG(LL_DEBUG, ("%p %d -> %d", nc, len, ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) {
|
|
||||||
struct mg_connection *nc = (struct mg_connection *) ctx;
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
struct pbuf *seg = cs->rx_chain;
|
|
||||||
if (seg == NULL) {
|
|
||||||
DBG(("%u - nothing to read", len));
|
|
||||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
|
||||||
}
|
|
||||||
size_t seg_len = (seg->len - cs->rx_offset);
|
|
||||||
DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
|
|
||||||
mgos_lock();
|
|
||||||
len = MIN(len, seg_len);
|
|
||||||
pbuf_copy_partial(seg, buf, len, cs->rx_offset);
|
|
||||||
cs->rx_offset += len;
|
|
||||||
/* TCP PCB may be NULL if connection has already been closed
|
|
||||||
* but we still have data to deliver to SSL. */
|
|
||||||
if (cs->pcb.tcp != NULL) tcp_recved(cs->pcb.tcp, len);
|
|
||||||
if (cs->rx_offset == cs->rx_chain->len) {
|
|
||||||
cs->rx_chain = pbuf_dechain(cs->rx_chain);
|
|
||||||
pbuf_free(seg);
|
|
||||||
cs->rx_offset = 0;
|
|
||||||
}
|
|
||||||
mgos_unlock();
|
|
||||||
LOG(LL_DEBUG, ("%p <- %d", nc, (int) len));
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MG_ENABLE_SSL && MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
|
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if CS_PLATFORM == CS_P_MSP432
|
#if CS_PLATFORM == CS_P_MSP432
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52) && \
|
#if (CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52) && \
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if MG_ENABLE_NET_IF_PIC32
|
#if MG_ENABLE_NET_IF_PIC32
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PIC32_NET_IF_H_
|
#ifndef CS_COMMON_PLATFORMS_PIC32_NET_IF_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3220_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3220_H_
|
||||||
@@ -22,7 +34,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MG_NET_IF MG_NET_IF_SIMPLELINK
|
#define MG_NET_IF MG_NET_IF_SIMPLELINK
|
||||||
|
#ifndef MG_SSL_IF
|
||||||
#define MG_SSL_IF MG_SSL_IF_SIMPLELINK
|
#define MG_SSL_IF MG_SSL_IF_SIMPLELINK
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Only SPIFFS supports directories, SLFS does not. */
|
/* Only SPIFFS supports directories, SLFS does not. */
|
||||||
#if defined(CC3220_FS_SPIFFS) && !defined(MG_ENABLE_DIRECTORY_LISTING)
|
#if defined(CC3220_FS_SPIFFS) && !defined(MG_ENABLE_DIRECTORY_LISTING)
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_
|
||||||
@@ -30,10 +42,6 @@ typedef struct stat cs_stat_t;
|
|||||||
#define __cdecl
|
#define __cdecl
|
||||||
#define _FILE_OFFSET_BITS 32
|
#define _FILE_OFFSET_BITS 32
|
||||||
|
|
||||||
#if !defined(RTOS_SDK) && !defined(__cplusplus)
|
|
||||||
#define fileno(x) -1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MG_LWIP 1
|
#define MG_LWIP 1
|
||||||
|
|
||||||
/* struct timeval is defined in sys/time.h. */
|
/* struct timeval is defined in sys/time.h. */
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_MBED_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_MBED_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_
|
||||||
#define CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_
|
#define CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_
|
||||||
#define CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_
|
#define CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2019 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_RS14100_H_
|
||||||
|
#define CS_COMMON_PLATFORMS_PLATFORM_RS14100_H_
|
||||||
|
#if CS_PLATFORM == CS_P_RS14100
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef MGOS_HAVE_VFS_COMMON
|
||||||
|
#include <mgos_vfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define to64(x) strtoll(x, NULL, 10)
|
||||||
|
#define INT64_FMT "lld"
|
||||||
|
#define SIZE_T_FMT "u"
|
||||||
|
typedef struct stat cs_stat_t;
|
||||||
|
#define DIRSEP '/'
|
||||||
|
|
||||||
|
#ifndef CS_ENABLE_STDIO
|
||||||
|
#define CS_ENABLE_STDIO 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_FILESYSTEM
|
||||||
|
#define MG_ENABLE_FILESYSTEM 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CS_PLATFORM == CS_P_RS14100 */
|
||||||
|
#endif /* CS_COMMON_PLATFORMS_PLATFORM_RS14100_H_ */
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_STM32_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_STM32_H_
|
||||||
@@ -22,7 +34,7 @@
|
|||||||
#include <stm32_sdk_hal.h>
|
#include <stm32_sdk_hal.h>
|
||||||
|
|
||||||
#define to64(x) strtoll(x, NULL, 10)
|
#define to64(x) strtoll(x, NULL, 10)
|
||||||
#define INT64_FMT PRId64
|
#define INT64_FMT "lld"
|
||||||
#define SIZE_T_FMT "u"
|
#define SIZE_T_FMT "u"
|
||||||
typedef struct stat cs_stat_t;
|
typedef struct stat cs_stat_t;
|
||||||
#define DIRSEP '/'
|
#define DIRSEP '/'
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_
|
#ifndef CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
|
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
|
||||||
@@ -157,7 +169,7 @@ int sl_set_ssl_opts(int sock, struct mg_connection *nc);
|
|||||||
|
|
||||||
#endif /* SL_MAJOR_VERSION_NUM < 2 */
|
#endif /* SL_MAJOR_VERSION_NUM < 2 */
|
||||||
|
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags);
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token);
|
||||||
|
|
||||||
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
|
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if MG_NET_IF == MG_NET_IF_SIMPLELINK && \
|
#if MG_NET_IF == MG_NET_IF_SIMPLELINK && \
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Standard libc interface to TI SimpleLink FS. */
|
/* Standard libc interface to TI SimpleLink FS. */
|
||||||
@@ -19,14 +31,14 @@
|
|||||||
#include "common/mg_mem.h"
|
#include "common/mg_mem.h"
|
||||||
|
|
||||||
#if SL_MAJOR_VERSION_NUM < 2
|
#if SL_MAJOR_VERSION_NUM < 2
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags) {
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token) {
|
||||||
_i32 fh;
|
_i32 fh;
|
||||||
_i32 r = sl_FsOpen(fname, flags, NULL /* token */, &fh);
|
_i32 r = sl_FsOpen(fname, flags, (unsigned long *) token, &fh);
|
||||||
return (r < 0 ? r : fh);
|
return (r < 0 ? r : fh);
|
||||||
}
|
}
|
||||||
#else /* SL_MAJOR_VERSION_NUM >= 2 */
|
#else /* SL_MAJOR_VERSION_NUM >= 2 */
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags) {
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token) {
|
||||||
return sl_FsOpen(fname, flags, NULL /* token */);
|
return sl_FsOpen(fname, flags, (unsigned long *) token);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -42,9 +54,11 @@ const char *drop_dir(const char *fname, bool *is_slfs);
|
|||||||
#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
|
#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sl_file_size_hint {
|
struct sl_file_open_info {
|
||||||
char *name;
|
char *name;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t *token;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sl_fd_info {
|
struct sl_fd_info {
|
||||||
@@ -54,7 +68,10 @@ struct sl_fd_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
|
static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
|
||||||
static struct sl_file_size_hint s_sl_file_size_hints[MAX_OPEN_SLFS_FILES];
|
static struct sl_file_open_info s_sl_file_open_infos[MAX_OPEN_SLFS_FILES];
|
||||||
|
|
||||||
|
static struct sl_file_open_info *fs_slfs_find_foi(const char *name,
|
||||||
|
bool create);
|
||||||
|
|
||||||
static int sl_fs_to_errno(_i32 r) {
|
static int sl_fs_to_errno(_i32 r) {
|
||||||
DBG(("SL error: %d", (int) r));
|
DBG(("SL error: %d", (int) r));
|
||||||
@@ -95,7 +112,13 @@ int fs_slfs_open(const char *pathname, int flags, mode_t mode) {
|
|||||||
_u32 am = 0;
|
_u32 am = 0;
|
||||||
fi->size = (size_t) -1;
|
fi->size = (size_t) -1;
|
||||||
int rw = (flags & 3);
|
int rw = (flags & 3);
|
||||||
size_t new_size = FS_SLFS_MAX_FILE_SIZE;
|
size_t new_size = 0;
|
||||||
|
struct sl_file_open_info *foi =
|
||||||
|
fs_slfs_find_foi(pathname, false /* create */);
|
||||||
|
if (foi != NULL) {
|
||||||
|
LOG(LL_DEBUG, ("FOI for %s: %d 0x%x %p", pathname, (int) foi->size,
|
||||||
|
(unsigned int) foi->flags, foi->token));
|
||||||
|
}
|
||||||
if (rw == O_RDONLY) {
|
if (rw == O_RDONLY) {
|
||||||
SlFsFileInfo_t sl_fi;
|
SlFsFileInfo_t sl_fi;
|
||||||
_i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi);
|
_i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi);
|
||||||
@@ -110,24 +133,27 @@ int fs_slfs_open(const char *pathname, int flags, mode_t mode) {
|
|||||||
return set_errno(ENOTSUP);
|
return set_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
if (flags & O_CREAT) {
|
if (flags & O_CREAT) {
|
||||||
size_t i;
|
if (foi->size > 0) {
|
||||||
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
new_size = foi->size;
|
||||||
if (s_sl_file_size_hints[i].name != NULL &&
|
} else {
|
||||||
strcmp(s_sl_file_size_hints[i].name, pathname) == 0) {
|
new_size = FS_SLFS_MAX_FILE_SIZE;
|
||||||
new_size = s_sl_file_size_hints[i].size;
|
|
||||||
MG_FREE(s_sl_file_size_hints[i].name);
|
|
||||||
s_sl_file_size_hints[i].name = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
am = FS_MODE_OPEN_CREATE(new_size, 0);
|
am = FS_MODE_OPEN_CREATE(new_size, 0);
|
||||||
} else {
|
} else {
|
||||||
am = SL_FS_WRITE;
|
am = SL_FS_WRITE;
|
||||||
}
|
}
|
||||||
|
#if SL_MAJOR_VERSION_NUM >= 2
|
||||||
|
am |= SL_FS_OVERWRITE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
fi->fh = slfs_open((_u8 *) pathname, am);
|
uint32_t *token = NULL;
|
||||||
LOG(LL_DEBUG, ("sl_FsOpen(%s, 0x%x) sz %u = %d", pathname, (int) am,
|
if (foi != NULL) {
|
||||||
(unsigned int) new_size, (int) fi->fh));
|
am |= foi->flags;
|
||||||
|
token = foi->token;
|
||||||
|
}
|
||||||
|
fi->fh = slfs_open((_u8 *) pathname, am, token);
|
||||||
|
LOG(LL_DEBUG, ("sl_FsOpen(%s, 0x%x, %p) sz %u = %d", pathname, (int) am,
|
||||||
|
token, (unsigned int) new_size, (int) fi->fh));
|
||||||
int r;
|
int r;
|
||||||
if (fi->fh >= 0) {
|
if (fi->fh >= 0) {
|
||||||
fi->pos = 0;
|
fi->pos = 0;
|
||||||
@@ -231,16 +257,46 @@ int fs_slfs_rename(const char *from, const char *to) {
|
|||||||
return set_errno(ENOTSUP);
|
return set_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_slfs_set_new_file_size(const char *name, size_t size) {
|
static struct sl_file_open_info *fs_slfs_find_foi(const char *name,
|
||||||
int i;
|
bool create) {
|
||||||
|
int i = 0;
|
||||||
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
||||||
if (s_sl_file_size_hints[i].name == NULL) {
|
if (s_sl_file_open_infos[i].name != NULL &&
|
||||||
DBG(("File size hint: %s %d", name, (int) size));
|
strcmp(drop_dir(s_sl_file_open_infos[i].name, NULL), name) == 0) {
|
||||||
s_sl_file_size_hints[i].name = strdup(name);
|
|
||||||
s_sl_file_size_hints[i].size = size;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (i != MAX_OPEN_SLFS_FILES) return &s_sl_file_open_infos[i];
|
||||||
|
if (!create) return NULL;
|
||||||
|
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
||||||
|
if (s_sl_file_open_infos[i].name == NULL) break;
|
||||||
|
}
|
||||||
|
if (i == MAX_OPEN_SLFS_FILES) {
|
||||||
|
i = 0; /* Evict a random slot. */
|
||||||
|
}
|
||||||
|
if (s_sl_file_open_infos[i].name != NULL) {
|
||||||
|
free(s_sl_file_open_infos[i].name);
|
||||||
|
}
|
||||||
|
s_sl_file_open_infos[i].name = strdup(name);
|
||||||
|
return &s_sl_file_open_infos[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_slfs_set_file_size(const char *name, size_t size) {
|
||||||
|
struct sl_file_open_info *foi = fs_slfs_find_foi(name, true /* create */);
|
||||||
|
foi->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_slfs_set_file_flags(const char *name, uint32_t flags, uint32_t *token) {
|
||||||
|
struct sl_file_open_info *foi = fs_slfs_find_foi(name, true /* create */);
|
||||||
|
foi->flags = flags;
|
||||||
|
foi->token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_slfs_unset_file_flags(const char *name) {
|
||||||
|
struct sl_file_open_info *foi = fs_slfs_find_foi(name, false /* create */);
|
||||||
|
if (foi == NULL) return;
|
||||||
|
free(foi->name);
|
||||||
|
memset(foi, 0, sizeof(*foi));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS) */
|
#endif /* defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS) */
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
|
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
|
||||||
@@ -27,7 +39,9 @@ off_t fs_slfs_lseek(int fd, off_t offset, int whence);
|
|||||||
int fs_slfs_unlink(const char *filename);
|
int fs_slfs_unlink(const char *filename);
|
||||||
int fs_slfs_rename(const char *from, const char *to);
|
int fs_slfs_rename(const char *from, const char *to);
|
||||||
|
|
||||||
void fs_slfs_set_new_file_size(const char *name, size_t size);
|
void fs_slfs_set_file_size(const char *name, size_t size);
|
||||||
|
void fs_slfs_set_file_flags(const char *name, uint32_t flags, uint32_t *token);
|
||||||
|
void fs_slfs_unset_file_flags(const char *name);
|
||||||
|
|
||||||
#endif /* defined(MG_FS_SLFS) */
|
#endif /* defined(MG_FS_SLFS) */
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/platforms/simplelink/sl_net_if.h"
|
#include "common/platforms/simplelink/sl_net_if.h"
|
||||||
@@ -17,7 +29,7 @@ static sock_t mg_open_listening_socket(struct mg_connection *nc,
|
|||||||
union socket_address *sa, int type,
|
union socket_address *sa, int type,
|
||||||
int proto);
|
int proto);
|
||||||
|
|
||||||
void mg_set_non_blocking_mode(sock_t sock) {
|
static void mg_set_non_blocking_mode(sock_t sock) {
|
||||||
SlSockNonblocking_t opt;
|
SlSockNonblocking_t opt;
|
||||||
#if SL_MAJOR_VERSION_NUM < 2
|
#if SL_MAJOR_VERSION_NUM < 2
|
||||||
opt.NonblockingEnabled = 1;
|
opt.NonblockingEnabled = 1;
|
||||||
@@ -31,17 +43,19 @@ static int mg_is_error(int n) {
|
|||||||
return (n < 0 && n != SL_ERROR_BSD_EALREADY && n != SL_ERROR_BSD_EAGAIN);
|
return (n < 0 && n != SL_ERROR_BSD_EALREADY && n != SL_ERROR_BSD_EAGAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_sl_if_connect_tcp(struct mg_connection *nc,
|
static void mg_sl_if_connect_tcp(struct mg_connection *nc,
|
||||||
const union socket_address *sa) {
|
const union socket_address *sa) {
|
||||||
int proto = 0;
|
int proto = 0;
|
||||||
|
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
|
||||||
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
|
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
|
||||||
|
#endif
|
||||||
sock_t sock = sl_Socket(AF_INET, SOCK_STREAM, proto);
|
sock_t sock = sl_Socket(AF_INET, SOCK_STREAM, proto);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
nc->err = sock;
|
nc->err = sock;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
mg_sock_set(nc, sock);
|
mg_sock_set(nc, sock);
|
||||||
#if MG_ENABLE_SSL
|
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
|
||||||
nc->err = sl_set_ssl_opts(sock, nc);
|
nc->err = sl_set_ssl_opts(sock, nc);
|
||||||
if (nc->err != 0) goto out;
|
if (nc->err != 0) goto out;
|
||||||
#endif
|
#endif
|
||||||
@@ -51,7 +65,7 @@ out:
|
|||||||
ntohs(sa->sin.sin_port), nc->sock, proto, nc->err));
|
ntohs(sa->sin.sin_port), nc->sock, proto, nc->err));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_sl_if_connect_udp(struct mg_connection *nc) {
|
static void mg_sl_if_connect_udp(struct mg_connection *nc) {
|
||||||
sock_t sock = sl_Socket(AF_INET, SOCK_DGRAM, 0);
|
sock_t sock = sl_Socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
nc->err = sock;
|
nc->err = sock;
|
||||||
@@ -61,7 +75,8 @@ void mg_sl_if_connect_udp(struct mg_connection *nc) {
|
|||||||
nc->err = 0;
|
nc->err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
|
static int mg_sl_if_listen_tcp(struct mg_connection *nc,
|
||||||
|
union socket_address *sa) {
|
||||||
int proto = 0;
|
int proto = 0;
|
||||||
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
|
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
|
||||||
sock_t sock = mg_open_listening_socket(nc, sa, SOCK_STREAM, proto);
|
sock_t sock = mg_open_listening_socket(nc, sa, SOCK_STREAM, proto);
|
||||||
@@ -70,27 +85,50 @@ int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
|
static int mg_sl_if_listen_udp(struct mg_connection *nc,
|
||||||
|
union socket_address *sa) {
|
||||||
sock_t sock = mg_open_listening_socket(nc, sa, SOCK_DGRAM, 0);
|
sock_t sock = mg_open_listening_socket(nc, sa, SOCK_DGRAM, 0);
|
||||||
if (sock == INVALID_SOCKET) return (errno ? errno : 1);
|
if (sock == INVALID_SOCKET) return (errno ? errno : 1);
|
||||||
mg_sock_set(nc, sock);
|
mg_sock_set(nc, sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) {
|
static int mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf,
|
||||||
mbuf_append(&nc->send_mbuf, buf, len);
|
size_t len) {
|
||||||
|
int n = (int) sl_Send(nc->sock, buf, len, 0);
|
||||||
|
if (n < 0 && !mg_is_error(n)) n = 0;
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_sl_if_udp_send(struct mg_connection *nc, const void *buf, size_t len) {
|
static int mg_sl_if_udp_send(struct mg_connection *nc, const void *buf,
|
||||||
mbuf_append(&nc->send_mbuf, buf, len);
|
size_t len) {
|
||||||
|
int n = sl_SendTo(nc->sock, buf, len, 0, &nc->sa.sa, sizeof(nc->sa.sin));
|
||||||
|
if (n < 0 && !mg_is_error(n)) n = 0;
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_sl_if_recved(struct mg_connection *nc, size_t len) {
|
static int mg_sl_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len) {
|
||||||
(void) nc;
|
int n = sl_Recv(nc->sock, buf, len, 0);
|
||||||
(void) len;
|
if (n == 0) {
|
||||||
|
/* Orderly shutdown of the socket, try flushing output. */
|
||||||
|
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||||
|
} else if (n < 0 && !mg_is_error(n)) {
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_sl_if_create_conn(struct mg_connection *nc) {
|
static int mg_sl_if_udp_recv(struct mg_connection *nc, void *buf, size_t len,
|
||||||
|
union socket_address *sa, size_t *sa_len) {
|
||||||
|
SlSocklen_t sa_len_t = *sa_len;
|
||||||
|
int n = sl_RecvFrom(nc->sock, buf, MG_UDP_RECV_BUFFER_SIZE, 0,
|
||||||
|
(SlSockAddr_t *) sa, &sa_len_t);
|
||||||
|
*sa_len = sa_len_t;
|
||||||
|
if (n < 0 && !mg_is_error(n)) n = 0;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mg_sl_if_create_conn(struct mg_connection *nc) {
|
||||||
(void) nc;
|
(void) nc;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -121,7 +159,6 @@ static int mg_accept_conn(struct mg_connection *lc) {
|
|||||||
DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr),
|
DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr),
|
||||||
ntohs(sa.sin.sin_port)));
|
ntohs(sa.sin.sin_port)));
|
||||||
mg_sock_set(nc, sock);
|
mg_sock_set(nc, sock);
|
||||||
if (nc->flags & MG_F_SSL) nc->flags |= MG_F_SSL_HANDSHAKE_DONE;
|
|
||||||
mg_if_accept_tcp_cb(nc, &sa, sa_len);
|
mg_if_accept_tcp_cb(nc, &sa, sa_len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -135,11 +172,11 @@ static sock_t mg_open_listening_socket(struct mg_connection *nc,
|
|||||||
(sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6);
|
(sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6);
|
||||||
sock_t sock = sl_Socket(sa->sa.sa_family, type, proto);
|
sock_t sock = sl_Socket(sa->sa.sa_family, type, proto);
|
||||||
if (sock < 0) return sock;
|
if (sock < 0) return sock;
|
||||||
|
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
|
||||||
|
if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
|
||||||
|
#endif
|
||||||
if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) goto clean;
|
if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) goto clean;
|
||||||
if (type != SOCK_DGRAM) {
|
if (type != SOCK_DGRAM) {
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
|
|
||||||
#endif
|
|
||||||
if ((r = sl_Listen(sock, SOMAXCONN)) < 0) goto clean;
|
if ((r = sl_Listen(sock, SOMAXCONN)) < 0) goto clean;
|
||||||
}
|
}
|
||||||
mg_set_non_blocking_mode(sock);
|
mg_set_non_blocking_mode(sock);
|
||||||
@@ -151,86 +188,18 @@ clean:
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_write_to_socket(struct mg_connection *nc) {
|
|
||||||
struct mbuf *io = &nc->send_mbuf;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
if (nc->flags & MG_F_UDP) {
|
|
||||||
n = sl_SendTo(nc->sock, io->buf, io->len, 0, &nc->sa.sa,
|
|
||||||
sizeof(nc->sa.sin));
|
|
||||||
DBG(("%p %d %d %d %s:%hu", nc, nc->sock, n, errno,
|
|
||||||
inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port)));
|
|
||||||
} else {
|
|
||||||
n = (int) sl_Send(nc->sock, io->buf, io->len, 0);
|
|
||||||
DBG(("%p %d bytes -> %d", nc, n, nc->sock));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n > 0) {
|
|
||||||
mg_if_sent_cb(nc, n);
|
|
||||||
} else if (n < 0 && mg_is_error(n)) {
|
|
||||||
/* Something went wrong, drop the connection. */
|
|
||||||
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max) {
|
|
||||||
size_t avail;
|
|
||||||
if (conn->recv_mbuf_limit < conn->recv_mbuf.len) return 0;
|
|
||||||
avail = conn->recv_mbuf_limit - conn->recv_mbuf.len;
|
|
||||||
return avail > max ? max : avail;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mg_handle_tcp_read(struct mg_connection *conn) {
|
|
||||||
int n = 0;
|
|
||||||
char *buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE);
|
|
||||||
|
|
||||||
if (buf == NULL) {
|
|
||||||
DBG(("OOM"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = (int) sl_Recv(conn->sock, buf,
|
|
||||||
recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0);
|
|
||||||
DBG(("%p %d bytes <- %d", conn, n, conn->sock));
|
|
||||||
if (n > 0) {
|
|
||||||
mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */);
|
|
||||||
} else {
|
|
||||||
MG_FREE(buf);
|
|
||||||
}
|
|
||||||
if (n == 0) {
|
|
||||||
/* Orderly shutdown of the socket, try flushing output. */
|
|
||||||
conn->flags |= MG_F_SEND_AND_CLOSE;
|
|
||||||
} else if (mg_is_error(n)) {
|
|
||||||
conn->flags |= MG_F_CLOSE_IMMEDIATELY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mg_handle_udp_read(struct mg_connection *nc) {
|
|
||||||
char *buf = (char *) MG_MALLOC(MG_UDP_RECV_BUFFER_SIZE);
|
|
||||||
if (buf == NULL) return;
|
|
||||||
union socket_address sa;
|
|
||||||
socklen_t sa_len = sizeof(sa);
|
|
||||||
int n = sl_RecvFrom(nc->sock, buf, MG_UDP_RECV_BUFFER_SIZE, 0,
|
|
||||||
(SlSockAddr_t *) &sa, &sa_len);
|
|
||||||
DBG(("%p %d bytes from %s:%d", nc, n, inet_ntoa(nc->sa.sin.sin_addr),
|
|
||||||
ntohs(nc->sa.sin.sin_port)));
|
|
||||||
if (n > 0) {
|
|
||||||
mg_if_recv_udp_cb(nc, buf, n, &sa, sa_len);
|
|
||||||
} else {
|
|
||||||
MG_FREE(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define _MG_F_FD_CAN_READ 1
|
#define _MG_F_FD_CAN_READ 1
|
||||||
#define _MG_F_FD_CAN_WRITE 1 << 1
|
#define _MG_F_FD_CAN_WRITE 1 << 1
|
||||||
#define _MG_F_FD_ERROR 1 << 2
|
#define _MG_F_FD_ERROR 1 << 2
|
||||||
|
|
||||||
void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
|
void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
|
||||||
DBG(("%p fd=%d fd_flags=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock,
|
DBG(("%p fd=%d fd_flags=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->sock,
|
||||||
fd_flags, nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
|
fd_flags, nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
|
||||||
|
|
||||||
|
if (!mg_if_poll(nc, now)) return;
|
||||||
|
|
||||||
if (nc->flags & MG_F_CONNECTING) {
|
if (nc->flags & MG_F_CONNECTING) {
|
||||||
if (nc->flags & MG_F_UDP || nc->err != SL_ERROR_BSD_EALREADY) {
|
if ((nc->flags & MG_F_UDP) || nc->err != SL_ERROR_BSD_EALREADY) {
|
||||||
mg_if_connect_cb(nc, nc->err);
|
mg_if_connect_cb(nc, nc->err);
|
||||||
} else {
|
} else {
|
||||||
/* In SimpleLink, to get status of non-blocking connect() we need to wait
|
/* In SimpleLink, to get status of non-blocking connect() we need to wait
|
||||||
@@ -252,9 +221,6 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
|
|||||||
) {
|
) {
|
||||||
nc->err = 0;
|
nc->err = 0;
|
||||||
}
|
}
|
||||||
if (nc->flags & MG_F_SSL && nc->err == 0) {
|
|
||||||
nc->flags |= MG_F_SSL_HANDSHAKE_DONE;
|
|
||||||
}
|
|
||||||
mg_if_connect_cb(nc, nc->err);
|
mg_if_connect_cb(nc, nc->err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,28 +230,21 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
|
|||||||
|
|
||||||
if (fd_flags & _MG_F_FD_CAN_READ) {
|
if (fd_flags & _MG_F_FD_CAN_READ) {
|
||||||
if (nc->flags & MG_F_UDP) {
|
if (nc->flags & MG_F_UDP) {
|
||||||
mg_handle_udp_read(nc);
|
mg_if_can_recv_cb(nc);
|
||||||
} else {
|
} else {
|
||||||
if (nc->flags & MG_F_LISTENING) {
|
if (nc->flags & MG_F_LISTENING) {
|
||||||
mg_accept_conn(nc);
|
mg_accept_conn(nc);
|
||||||
} else {
|
} else {
|
||||||
mg_handle_tcp_read(nc);
|
mg_if_can_recv_cb(nc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
|
if (fd_flags & _MG_F_FD_CAN_WRITE) {
|
||||||
if ((fd_flags & _MG_F_FD_CAN_WRITE) && nc->send_mbuf.len > 0) {
|
mg_if_can_send_cb(nc);
|
||||||
mg_write_to_socket(nc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(fd_flags & (_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE))) {
|
|
||||||
mg_if_poll(nc, now);
|
|
||||||
}
|
|
||||||
mg_if_timer(nc, now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags,
|
DBG(("%p after fd=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->sock, nc->flags,
|
||||||
(int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
|
(int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,14 +365,6 @@ time_t mg_sl_if_poll(struct mg_iface *iface, int timeout_ms) {
|
|||||||
mg_mgr_handle_conn(nc, fd_flags, now);
|
mg_mgr_handle_conn(nc, fd_flags, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nc = mgr->active_connections; nc != NULL; nc = tmp) {
|
|
||||||
tmp = nc->next;
|
|
||||||
if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) ||
|
|
||||||
(nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) {
|
|
||||||
mg_close_conn(nc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +415,8 @@ void sl_restart_cb(struct mg_mgr *mgr) {
|
|||||||
mg_sl_if_connect_udp, \
|
mg_sl_if_connect_udp, \
|
||||||
mg_sl_if_tcp_send, \
|
mg_sl_if_tcp_send, \
|
||||||
mg_sl_if_udp_send, \
|
mg_sl_if_udp_send, \
|
||||||
mg_sl_if_recved, \
|
mg_sl_if_tcp_recv, \
|
||||||
|
mg_sl_if_udp_recv, \
|
||||||
mg_sl_if_create_conn, \
|
mg_sl_if_create_conn, \
|
||||||
mg_sl_if_destroy_conn, \
|
mg_sl_if_destroy_conn, \
|
||||||
mg_sl_if_sock_set, \
|
mg_sl_if_sock_set, \
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_
|
#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if MG_NET_IF == MG_NET_IF_SIMPLELINK
|
#if MG_NET_IF == MG_NET_IF_SIMPLELINK
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
|
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
|
||||||
@@ -54,6 +66,31 @@ enum mg_ssl_if_result mg_ssl_if_conn_init(
|
|||||||
return MG_SSL_OK;
|
return MG_SSL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc,
|
||||||
|
struct mg_connection *lc) {
|
||||||
|
/* SimpleLink does everything for us, nothing for us to do. */
|
||||||
|
(void) nc;
|
||||||
|
(void) lc;
|
||||||
|
return MG_SSL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc) {
|
||||||
|
/* SimpleLink has already performed the handshake, nothing to do. */
|
||||||
|
return MG_SSL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_ssl_if_read(struct mg_connection *nc, void *buf, size_t len) {
|
||||||
|
/* SimpelLink handles TLS, so this is just a pass-through. */
|
||||||
|
int n = nc->iface->vtable->tcp_recv(nc, buf, len);
|
||||||
|
if (n == 0) nc->flags |= MG_F_WANT_READ;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_ssl_if_write(struct mg_connection *nc, const void *buf, size_t len) {
|
||||||
|
/* SimpelLink handles TLS, so this is just a pass-through. */
|
||||||
|
return nc->iface->vtable->tcp_send(nc, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
void mg_ssl_if_conn_close_notify(struct mg_connection *nc) {
|
void mg_ssl_if_conn_close_notify(struct mg_connection *nc) {
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
(void) nc;
|
(void) nc;
|
||||||
@@ -78,9 +115,9 @@ bool pem_to_der(const char *pem_file, const char *der_file) {
|
|||||||
pf = fopen(pem_file, "r");
|
pf = fopen(pem_file, "r");
|
||||||
if (pf == NULL) goto clean;
|
if (pf == NULL) goto clean;
|
||||||
remove(der_file);
|
remove(der_file);
|
||||||
fs_slfs_set_new_file_size(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN,
|
fs_slfs_set_file_size(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN, 2048);
|
||||||
2048);
|
|
||||||
df = fopen(der_file, "w");
|
df = fopen(der_file, "w");
|
||||||
|
fs_slfs_unset_file_flags(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN);
|
||||||
if (df == NULL) goto clean;
|
if (df == NULL) goto clean;
|
||||||
while (1) {
|
while (1) {
|
||||||
char pem_buf[70];
|
char pem_buf[70];
|
||||||
@@ -154,56 +191,59 @@ int sl_set_ssl_opts(int sock, struct mg_connection *nc) {
|
|||||||
const struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
|
const struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
|
||||||
DBG(("%p ssl ctx: %p", nc, ctx));
|
DBG(("%p ssl ctx: %p", nc, ctx));
|
||||||
|
|
||||||
if (ctx != NULL) {
|
if (ctx == NULL) return 0;
|
||||||
DBG(("%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert : "-"),
|
DBG(("%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert : "-"),
|
||||||
(ctx->ssl_key ? ctx->ssl_cert : "-"),
|
(ctx->ssl_key ? ctx->ssl_cert : "-"),
|
||||||
(ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"),
|
(ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"),
|
||||||
(ctx->ssl_server_name ? ctx->ssl_server_name : "-")));
|
(ctx->ssl_server_name ? ctx->ssl_server_name : "-")));
|
||||||
if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) {
|
if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) {
|
||||||
char *ssl_cert = sl_pem2der(ctx->ssl_cert);
|
char *ssl_cert = sl_pem2der(ctx->ssl_cert), *ssl_key = NULL;
|
||||||
char *ssl_key = sl_pem2der(ctx->ssl_key);
|
if (ssl_cert != NULL) {
|
||||||
if (ssl_cert != NULL && ssl_key != NULL) {
|
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
||||||
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
|
||||||
SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
|
strlen(ssl_cert));
|
||||||
strlen(ssl_cert));
|
MG_FREE(ssl_cert);
|
||||||
LOG(LL_INFO, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
|
LOG(LL_DEBUG, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
|
||||||
|
ssl_key = sl_pem2der(ctx->ssl_key);
|
||||||
|
if (ssl_key != NULL) {
|
||||||
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
||||||
SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key,
|
SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key,
|
||||||
strlen(ssl_key));
|
strlen(ssl_key));
|
||||||
LOG(LL_INFO, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
|
MG_FREE(ssl_key);
|
||||||
|
LOG(LL_DEBUG, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
|
||||||
} else {
|
} else {
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
MG_FREE(ssl_cert);
|
} else {
|
||||||
MG_FREE(ssl_key);
|
err = -1;
|
||||||
|
}
|
||||||
|
if (err != 0) return err;
|
||||||
|
}
|
||||||
|
if (ctx->ssl_ca_cert != NULL) {
|
||||||
|
if (ctx->ssl_ca_cert[0] != '\0') {
|
||||||
|
char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
|
||||||
|
if (ssl_ca_cert != NULL) {
|
||||||
|
err =
|
||||||
|
sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME,
|
||||||
|
ssl_ca_cert, strlen(ssl_ca_cert));
|
||||||
|
LOG(LL_DEBUG, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
|
||||||
|
} else {
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
MG_FREE(ssl_ca_cert);
|
||||||
if (err != 0) return err;
|
if (err != 0) return err;
|
||||||
}
|
}
|
||||||
if (ctx->ssl_ca_cert != NULL) {
|
}
|
||||||
if (ctx->ssl_ca_cert[0] != '\0') {
|
if (ctx->ssl_server_name != NULL) {
|
||||||
char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
|
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
||||||
if (ssl_ca_cert != NULL) {
|
SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
|
||||||
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
ctx->ssl_server_name, strlen(ctx->ssl_server_name));
|
||||||
SL_SO_SECURE_FILES_CA_FILE_NAME, ssl_ca_cert,
|
DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
|
||||||
strlen(ssl_ca_cert));
|
/* Domain name verificationw as added in a NWP service pack, older
|
||||||
LOG(LL_INFO, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
|
* versions return SL_ERROR_BSD_ENOPROTOOPT. There isn't much we can do
|
||||||
} else {
|
* about it,
|
||||||
err = -1;
|
* so we ignore the error. */
|
||||||
}
|
if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT) return err;
|
||||||
MG_FREE(ssl_ca_cert);
|
|
||||||
if (err != 0) return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ctx->ssl_server_name != NULL) {
|
|
||||||
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
|
||||||
SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
|
|
||||||
ctx->ssl_server_name, strlen(ctx->ssl_server_name));
|
|
||||||
DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
|
|
||||||
/* Domain name verificationw as added in a NWP service pack, older
|
|
||||||
* versions return SL_ERROR_BSD_ENOPROTOOPT. There isn't much we can do
|
|
||||||
* about it,
|
|
||||||
* so we ignore the error. */
|
|
||||||
if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT) return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
Copyright (c) 2011 The stlink project (github.com/texane/stlink) contributors.
|
|
||||||
All rights reserved.
|
|
||||||
Copyright (c) 2011 The "Capt'ns Missing Link" Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer in the documentation and/or other materials provided
|
|
||||||
with the distribution.
|
|
||||||
* Neither the name of Martin Capitanio nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1,869 +0,0 @@
|
|||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include "stlink.h"
|
|
||||||
#include "usb.h"
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#define O_BINARY 0 //! @todo get rid of this OH MY (@xor-gate)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* todo: stm32l15xxx flash memory, pm0062 manual */
|
|
||||||
|
|
||||||
/* stm32f FPEC flash controller interface, pm0063 manual */
|
|
||||||
// TODO - all of this needs to be abstracted out....
|
|
||||||
// STM32F05x is identical, based on RM0091 (DM00031936, Doc ID 018940 Rev 2,
|
|
||||||
// August 2012)
|
|
||||||
#define FLASH_REGS_ADDR 0x40022000
|
|
||||||
#define FLASH_REGS_SIZE 0x28
|
|
||||||
|
|
||||||
#define FLASH_ACR (FLASH_REGS_ADDR + 0x00)
|
|
||||||
#define FLASH_KEYR (FLASH_REGS_ADDR + 0x04)
|
|
||||||
#define FLASH_SR (FLASH_REGS_ADDR + 0x0c)
|
|
||||||
#define FLASH_CR (FLASH_REGS_ADDR + 0x10)
|
|
||||||
#define FLASH_AR (FLASH_REGS_ADDR + 0x14)
|
|
||||||
#define FLASH_OBR (FLASH_REGS_ADDR + 0x1c)
|
|
||||||
#define FLASH_WRPR (FLASH_REGS_ADDR + 0x20)
|
|
||||||
|
|
||||||
// For STM32F05x, the RDPTR_KEY may be wrong, but as it is not used anywhere...
|
|
||||||
#define FLASH_RDPTR_KEY 0x00a5
|
|
||||||
#define FLASH_KEY1 0x45670123
|
|
||||||
#define FLASH_KEY2 0xcdef89ab
|
|
||||||
|
|
||||||
#define FLASH_SR_BSY 0
|
|
||||||
#define FLASH_SR_EOP 5
|
|
||||||
|
|
||||||
#define FLASH_CR_PG 0
|
|
||||||
#define FLASH_CR_PER 1
|
|
||||||
#define FLASH_CR_MER 2
|
|
||||||
#define FLASH_CR_STRT 6
|
|
||||||
#define FLASH_CR_LOCK 7
|
|
||||||
|
|
||||||
// 32L = 32F1 same CoreID as 32F4!
|
|
||||||
#define STM32L_FLASH_REGS_ADDR ((uint32_t) 0x40023c00)
|
|
||||||
#define STM32L_FLASH_ACR (STM32L_FLASH_REGS_ADDR + 0x00)
|
|
||||||
#define STM32L_FLASH_PECR (STM32L_FLASH_REGS_ADDR + 0x04)
|
|
||||||
#define STM32L_FLASH_PDKEYR (STM32L_FLASH_REGS_ADDR + 0x08)
|
|
||||||
#define STM32L_FLASH_PEKEYR (STM32L_FLASH_REGS_ADDR + 0x0c)
|
|
||||||
#define STM32L_FLASH_PRGKEYR (STM32L_FLASH_REGS_ADDR + 0x10)
|
|
||||||
#define STM32L_FLASH_OPTKEYR (STM32L_FLASH_REGS_ADDR + 0x14)
|
|
||||||
#define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18)
|
|
||||||
#define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x1c)
|
|
||||||
#define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20)
|
|
||||||
#define FLASH_L1_FPRG 10
|
|
||||||
#define FLASH_L1_PROG 3
|
|
||||||
|
|
||||||
// 32L4 register base is at FLASH_REGS_ADDR (0x40022000)
|
|
||||||
#define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08)
|
|
||||||
#define STM32L4_FLASH_SR (FLASH_REGS_ADDR + 0x10)
|
|
||||||
#define STM32L4_FLASH_CR (FLASH_REGS_ADDR + 0x14)
|
|
||||||
#define STM32L4_FLASH_OPTR (FLASH_REGS_ADDR + 0x20)
|
|
||||||
|
|
||||||
#define STM32L4_FLASH_SR_BSY 16
|
|
||||||
#define STM32L4_FLASH_SR_ERRMASK 0x3f8 /* SR [9:3] */
|
|
||||||
|
|
||||||
#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */
|
|
||||||
#define STM32L4_FLASH_CR_PG 0 /* Program */
|
|
||||||
#define STM32L4_FLASH_CR_PER 1 /* Page erase */
|
|
||||||
#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */
|
|
||||||
#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */
|
|
||||||
#define STM32L4_FLASH_CR_STRT 16 /* Start command */
|
|
||||||
#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */
|
|
||||||
#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */
|
|
||||||
// Bits requesting flash operations (useful when we want to clear them)
|
|
||||||
#define STM32L4_FLASH_CR_OPBITS \
|
|
||||||
((1lu << STM32L4_FLASH_CR_PG) | (1lu << STM32L4_FLASH_CR_PER) | \
|
|
||||||
(1lu << STM32L4_FLASH_CR_MER1) | (1lu << STM32L4_FLASH_CR_MER1))
|
|
||||||
// Page is fully specified by BKER and PNB
|
|
||||||
#define STM32L4_FLASH_CR_PAGEMASK (0x1fflu << STM32L4_FLASH_CR_PNB)
|
|
||||||
|
|
||||||
#define STM32L4_FLASH_OPTR_DUALBANK 21
|
|
||||||
|
|
||||||
// STM32L0x flash register base and offsets
|
|
||||||
// same as 32L1 above
|
|
||||||
// RM0090 - DM00031020.pdf
|
|
||||||
#define STM32L0_FLASH_REGS_ADDR ((uint32_t) 0x40022000)
|
|
||||||
#define FLASH_ACR_OFF ((uint32_t) 0x00)
|
|
||||||
#define FLASH_PECR_OFF ((uint32_t) 0x04)
|
|
||||||
#define FLASH_PDKEYR_OFF ((uint32_t) 0x08)
|
|
||||||
#define FLASH_PEKEYR_OFF ((uint32_t) 0x0c)
|
|
||||||
#define FLASH_PRGKEYR_OFF ((uint32_t) 0x10)
|
|
||||||
#define FLASH_OPTKEYR_OFF ((uint32_t) 0x14)
|
|
||||||
#define FLASH_SR_OFF ((uint32_t) 0x18)
|
|
||||||
#define FLASH_OBR_OFF ((uint32_t) 0x1c)
|
|
||||||
#define FLASH_WRPR_OFF ((uint32_t) 0x20)
|
|
||||||
|
|
||||||
// STM32F4
|
|
||||||
#define FLASH_F4_REGS_ADDR ((uint32_t) 0x40023c00)
|
|
||||||
#define FLASH_F4_KEYR (FLASH_F4_REGS_ADDR + 0x04)
|
|
||||||
#define FLASH_F4_OPT_KEYR (FLASH_F4_REGS_ADDR + 0x08)
|
|
||||||
#define FLASH_F4_SR (FLASH_F4_REGS_ADDR + 0x0c)
|
|
||||||
#define FLASH_F4_CR (FLASH_F4_REGS_ADDR + 0x10)
|
|
||||||
#define FLASH_F4_OPT_CR (FLASH_F4_REGS_ADDR + 0x14)
|
|
||||||
#define FLASH_F4_CR_STRT 16
|
|
||||||
#define FLASH_F4_CR_LOCK 31
|
|
||||||
#define FLASH_F4_CR_SER 1
|
|
||||||
#define FLASH_F4_CR_SNB 3
|
|
||||||
#define FLASH_F4_CR_SNB_MASK 0xf8
|
|
||||||
#define FLASH_F4_SR_BSY 16
|
|
||||||
|
|
||||||
#define L1_WRITE_BLOCK_SIZE 0x80
|
|
||||||
#define L0_WRITE_BLOCK_SIZE 0x40
|
|
||||||
|
|
||||||
#define STLINK_REG_CM3_CPUID 0xE000ED00
|
|
||||||
#define STLINK_REG_CM3_FP_CTRL 0xE0002000
|
|
||||||
#define STLINK_REG_CM3_FP_COMP0 0xE0002008
|
|
||||||
|
|
||||||
/* Cortex™-M3 Technical Reference Manual */
|
|
||||||
/* Debug Halting Control and Status Register */
|
|
||||||
#define STLINK_REG_DHCSR 0xe000edf0
|
|
||||||
#define STLINK_REG_DHCSR_DBGKEY 0xa05f0000
|
|
||||||
#define STLINK_REG_DCRSR 0xe000edf4
|
|
||||||
#define STLINK_REG_DCRDR 0xe000edf8
|
|
||||||
|
|
||||||
struct stlink_chipid_params {
|
|
||||||
uint32_t chip_id;
|
|
||||||
char *description;
|
|
||||||
uint32_t flash_size_reg;
|
|
||||||
uint32_t flash_pagesize;
|
|
||||||
uint32_t sram_size;
|
|
||||||
uint32_t bootrom_base;
|
|
||||||
uint32_t bootrom_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
void write_uint32(unsigned char *buf, uint32_t ui) {
|
|
||||||
if (!is_bigendian()) { // le -> le (don't swap)
|
|
||||||
buf[0] = ((unsigned char *) &ui)[0];
|
|
||||||
buf[1] = ((unsigned char *) &ui)[1];
|
|
||||||
buf[2] = ((unsigned char *) &ui)[2];
|
|
||||||
buf[3] = ((unsigned char *) &ui)[3];
|
|
||||||
} else {
|
|
||||||
buf[0] = ((unsigned char *) &ui)[3];
|
|
||||||
buf[1] = ((unsigned char *) &ui)[2];
|
|
||||||
buf[2] = ((unsigned char *) &ui)[1];
|
|
||||||
buf[3] = ((unsigned char *) &ui)[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_uint16(unsigned char *buf, uint16_t ui) {
|
|
||||||
if (!is_bigendian()) { // le -> le (don't swap)
|
|
||||||
buf[0] = ((unsigned char *) &ui)[0];
|
|
||||||
buf[1] = ((unsigned char *) &ui)[1];
|
|
||||||
} else {
|
|
||||||
buf[0] = ((unsigned char *) &ui)[1];
|
|
||||||
buf[1] = ((unsigned char *) &ui)[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t read_uint32(const unsigned char *c, const int pt) {
|
|
||||||
uint32_t ui;
|
|
||||||
char *p = (char *) &ui;
|
|
||||||
|
|
||||||
if (!is_bigendian()) { // le -> le (don't swap)
|
|
||||||
p[0] = c[pt + 0];
|
|
||||||
p[1] = c[pt + 1];
|
|
||||||
p[2] = c[pt + 2];
|
|
||||||
p[3] = c[pt + 3];
|
|
||||||
} else {
|
|
||||||
p[0] = c[pt + 3];
|
|
||||||
p[1] = c[pt + 2];
|
|
||||||
p[2] = c[pt + 1];
|
|
||||||
p[3] = c[pt + 0];
|
|
||||||
}
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t __attribute__((unused)) read_flash_rdp(stlink_t *sl) {
|
|
||||||
uint32_t rdp;
|
|
||||||
stlink_read_debug32(sl, FLASH_WRPR, &rdp);
|
|
||||||
return rdp & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t read_flash_cr(stlink_t *sl) {
|
|
||||||
uint32_t res;
|
|
||||||
stlink_read_debug32(sl, FLASH_F4_CR, &res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int is_flash_locked(stlink_t *sl) {
|
|
||||||
/* return non zero for true */
|
|
||||||
uint32_t cr_lock_shift = FLASH_F4_CR_LOCK, cr = read_flash_cr(sl);
|
|
||||||
return cr & (1 << cr_lock_shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unlock_flash(stlink_t *sl) {
|
|
||||||
uint32_t key_reg = FLASH_F4_KEYR;
|
|
||||||
stlink_write_debug32(sl, key_reg, FLASH_KEY1);
|
|
||||||
stlink_write_debug32(sl, key_reg, FLASH_KEY2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int unlock_flash_if(stlink_t *sl) {
|
|
||||||
/* unlock flash if already locked */
|
|
||||||
|
|
||||||
if (is_flash_locked(sl)) {
|
|
||||||
unlock_flash(sl);
|
|
||||||
if (is_flash_locked(sl)) {
|
|
||||||
printf("Failed to unlock flash!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lock_flash(stlink_t *sl) {
|
|
||||||
uint32_t n;
|
|
||||||
uint32_t cr_reg = FLASH_F4_CR;
|
|
||||||
uint32_t cr_lock_shift = FLASH_F4_CR_LOCK;
|
|
||||||
|
|
||||||
n = read_flash_cr(sl) | (1 << cr_lock_shift);
|
|
||||||
stlink_write_debug32(sl, cr_reg, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_flash_cr_pg(stlink_t *sl) {
|
|
||||||
uint32_t cr_reg, x;
|
|
||||||
|
|
||||||
x = read_flash_cr(sl);
|
|
||||||
|
|
||||||
cr_reg = FLASH_F4_CR;
|
|
||||||
x |= 1 << FLASH_CR_PG;
|
|
||||||
|
|
||||||
stlink_write_debug32(sl, cr_reg, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) clear_flash_cr_pg(stlink_t *sl) {
|
|
||||||
uint32_t cr_reg, n;
|
|
||||||
|
|
||||||
cr_reg = FLASH_F4_CR;
|
|
||||||
|
|
||||||
n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
|
|
||||||
stlink_write_debug32(sl, cr_reg, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_flash_cr_per(stlink_t *sl) {
|
|
||||||
const uint32_t n = 1 << FLASH_CR_PER;
|
|
||||||
stlink_write_debug32(sl, FLASH_CR, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) clear_flash_cr_per(stlink_t *sl) {
|
|
||||||
const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PER);
|
|
||||||
stlink_write_debug32(sl, FLASH_CR, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_flash_cr_mer(stlink_t *sl, bool v) {
|
|
||||||
uint32_t val, cr_reg, cr_mer, cr_pg;
|
|
||||||
|
|
||||||
cr_reg = FLASH_F4_CR;
|
|
||||||
cr_mer = 1 << FLASH_CR_MER;
|
|
||||||
cr_pg = 1 << FLASH_CR_PG;
|
|
||||||
|
|
||||||
stlink_read_debug32(sl, cr_reg, &val);
|
|
||||||
if (val & cr_pg) {
|
|
||||||
/* STM32F030 will drop MER bit if PG was set */
|
|
||||||
val &= ~cr_pg;
|
|
||||||
stlink_write_debug32(sl, cr_reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v)
|
|
||||||
val |= cr_mer;
|
|
||||||
else
|
|
||||||
val &= ~cr_mer;
|
|
||||||
stlink_write_debug32(sl, cr_reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
|
|
||||||
uint32_t val, cr_reg, cr_mer;
|
|
||||||
|
|
||||||
cr_reg = FLASH_F4_CR;
|
|
||||||
cr_mer = 1 << FLASH_CR_MER;
|
|
||||||
|
|
||||||
stlink_read_debug32(sl, cr_reg, &val);
|
|
||||||
val &= ~cr_mer;
|
|
||||||
stlink_write_debug32(sl, cr_reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_flash_cr_strt(stlink_t *sl) {
|
|
||||||
uint32_t val, cr_reg, cr_strt;
|
|
||||||
|
|
||||||
cr_reg = FLASH_F4_CR;
|
|
||||||
cr_strt = 1 << FLASH_F4_CR_STRT;
|
|
||||||
|
|
||||||
stlink_read_debug32(sl, cr_reg, &val);
|
|
||||||
val |= cr_strt;
|
|
||||||
stlink_write_debug32(sl, cr_reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t read_flash_sr(stlink_t *sl) {
|
|
||||||
uint32_t res, sr_reg;
|
|
||||||
sr_reg = FLASH_F4_SR;
|
|
||||||
stlink_read_debug32(sl, sr_reg, &res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int is_flash_busy(stlink_t *sl) {
|
|
||||||
uint32_t sr_busy_shift;
|
|
||||||
sr_busy_shift = FLASH_F4_SR_BSY;
|
|
||||||
return read_flash_sr(sl) & (1 << sr_busy_shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wait_flash_busy(stlink_t *sl) {
|
|
||||||
/* todo: add some delays here */
|
|
||||||
while (is_flash_busy(sl))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wait_flash_busy_progress(stlink_t *sl) {
|
|
||||||
while (is_flash_busy(sl)) {
|
|
||||||
usleep(10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int is_flash_eop(stlink_t *sl) {
|
|
||||||
return read_flash_sr(sl) & (1 << FLASH_SR_EOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) clear_flash_sr_eop(stlink_t *sl) {
|
|
||||||
const uint32_t n = read_flash_sr(sl) & ~(1 << FLASH_SR_EOP);
|
|
||||||
stlink_write_debug32(sl, FLASH_SR, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) wait_flash_eop(stlink_t *sl) {
|
|
||||||
/* todo: add some delays here */
|
|
||||||
while (is_flash_eop(sl) == 0)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void write_flash_ar(stlink_t *sl, uint32_t n) {
|
|
||||||
stlink_write_debug32(sl, FLASH_AR, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void write_flash_cr_psiz(stlink_t *sl, uint32_t n) {
|
|
||||||
uint32_t x = read_flash_cr(sl);
|
|
||||||
x &= ~(0x03 << 8);
|
|
||||||
x |= (n << 8);
|
|
||||||
stlink_write_debug32(sl, FLASH_F4_CR, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n) {
|
|
||||||
uint32_t x = read_flash_cr(sl);
|
|
||||||
x &= ~FLASH_F4_CR_SNB_MASK;
|
|
||||||
x |= (n << FLASH_F4_CR_SNB);
|
|
||||||
x |= (1 << FLASH_F4_CR_SER);
|
|
||||||
stlink_write_debug32(sl, FLASH_F4_CR, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void write_flash_cr_bker_pnb(stlink_t *sl, uint32_t n) {
|
|
||||||
stlink_write_debug32(sl, STM32L4_FLASH_SR,
|
|
||||||
0xFFFFFFFF & ~(1 << STM32L4_FLASH_SR_BSY));
|
|
||||||
uint32_t x = read_flash_cr(sl);
|
|
||||||
x &= ~STM32L4_FLASH_CR_OPBITS;
|
|
||||||
x &= ~STM32L4_FLASH_CR_PAGEMASK;
|
|
||||||
x &= ~(1 << STM32L4_FLASH_CR_MER1);
|
|
||||||
x &= ~(1 << STM32L4_FLASH_CR_MER2);
|
|
||||||
x |= (n << STM32L4_FLASH_CR_PNB);
|
|
||||||
x |= (1lu << STM32L4_FLASH_CR_PER);
|
|
||||||
stlink_write_debug32(sl, STM32L4_FLASH_CR, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stlink_close(stlink_t *sl) {
|
|
||||||
if (!sl) return;
|
|
||||||
_stlink_usb_close(sl);
|
|
||||||
free(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_exit_debug_mode(stlink_t *sl) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY);
|
|
||||||
if (ret == -1) return ret;
|
|
||||||
|
|
||||||
return _stlink_usb_exit_debug_mode(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_enter_swd_mode(stlink_t *sl) {
|
|
||||||
return _stlink_usb_enter_swd_mode(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force the core into the debug mode -> halted state.
|
|
||||||
int stlink_force_debug(stlink_t *sl) {
|
|
||||||
return _stlink_usb_force_debug(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_exit_dfu_mode(stlink_t *sl) {
|
|
||||||
return _stlink_usb_exit_dfu_mode(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_core_id(stlink_t *sl) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = _stlink_usb_core_id(sl);
|
|
||||||
if (ret == -1) {
|
|
||||||
printf("Failed to read core_id\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_chip_id(stlink_t *sl, uint32_t *chip_id) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = stlink_read_debug32(sl, 0xE0042000, chip_id);
|
|
||||||
if (ret == -1) return ret;
|
|
||||||
|
|
||||||
if (*chip_id == 0)
|
|
||||||
ret = stlink_read_debug32(
|
|
||||||
sl, 0x40015800,
|
|
||||||
chip_id); // Try Corex M0 DBGMCU_IDCODE register address
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reads and decodes the flash parameters, as dynamically as possible
|
|
||||||
* @param sl
|
|
||||||
* @return 0 for success, or -1 for unsupported core type.
|
|
||||||
*/
|
|
||||||
static const struct stlink_chipid_params F7_params = {
|
|
||||||
// RM0385 and DS10916 document was used to find these paramaters
|
|
||||||
.chip_id = STLINK_CHIPID_STM32_F7,
|
|
||||||
.description = "F7 device",
|
|
||||||
.flash_size_reg = 0x1ff0f442, // section 41.2
|
|
||||||
.flash_pagesize = 0x800, // No flash pages
|
|
||||||
.sram_size = 0x50000, // "SRAM" byte size in hex from DS Fig 18
|
|
||||||
.bootrom_base =
|
|
||||||
0x00100000, // "System memory" starting address from DS Fig 18
|
|
||||||
.bootrom_size = 0xEDC0 // "System memory" byte size in hex from DS Fig 18
|
|
||||||
};
|
|
||||||
|
|
||||||
int stlink_load_device_params(stlink_t *sl) {
|
|
||||||
const struct stlink_chipid_params *params = &F7_params;
|
|
||||||
stlink_core_id(sl);
|
|
||||||
uint32_t chip_id;
|
|
||||||
uint32_t flash_size;
|
|
||||||
|
|
||||||
stlink_chip_id(sl, &chip_id);
|
|
||||||
sl->chip_id = chip_id & 0xfff;
|
|
||||||
/* Fix chip_id for F4 rev A errata , Read CPU ID, as CoreID is the same for
|
|
||||||
* F2/F4*/
|
|
||||||
if (sl->chip_id == 0x411) {
|
|
||||||
uint32_t cpuid;
|
|
||||||
stlink_read_debug32(sl, 0xE000ED00, &cpuid);
|
|
||||||
if ((cpuid & 0xfff0) == 0xc240) sl->chip_id = 0x413;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sl->chip_id != STLINK_CHIPID_STM32_F7) {
|
|
||||||
printf("unsupported chip id! %d\n", chip_id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are fixed...
|
|
||||||
sl->flash_base = STM32_FLASH_BASE;
|
|
||||||
sl->sram_base = STM32_SRAM_BASE;
|
|
||||||
stlink_read_debug32(sl, (params->flash_size_reg) & ~3, &flash_size);
|
|
||||||
if (params->flash_size_reg & 2) flash_size = flash_size >> 16;
|
|
||||||
flash_size = flash_size & 0xffff;
|
|
||||||
|
|
||||||
sl->flash_size = flash_size * 1024;
|
|
||||||
sl->flash_pgsz = params->flash_pagesize;
|
|
||||||
sl->sram_size = params->sram_size;
|
|
||||||
sl->sys_base = params->bootrom_base;
|
|
||||||
sl->sys_size = params->bootrom_size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_reset(stlink_t *sl) {
|
|
||||||
return _stlink_usb_reset(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_jtag_reset(stlink_t *sl, int value) {
|
|
||||||
return _stlink_usb_jtag_reset(sl, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_run(stlink_t *sl) {
|
|
||||||
return _stlink_usb_run(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_set_swdclk(stlink_t *sl, uint16_t divisor) {
|
|
||||||
return _stlink_usb_set_swdclk(sl, divisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_status(stlink_t *sl) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = _stlink_usb_status(sl);
|
|
||||||
stlink_core_stat(sl);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_target_voltage(stlink_t *sl) {
|
|
||||||
return _stlink_usb_target_voltage(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
|
|
||||||
return _stlink_usb_read_debug32(sl, addr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
|
|
||||||
return _stlink_usb_write_debug32(sl, addr, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
|
|
||||||
if (len % 4 != 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error: Data length doesn't have a 32 bit alignment: +%d byte.\n",
|
|
||||||
len % 4);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
return _stlink_usb_write_mem32(sl, addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
|
|
||||||
if (len % 4 != 0) { // !!! never ever: fw gives just wrong values
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error: Data length doesn't have a 32 bit alignment: +%d byte.\n",
|
|
||||||
len % 4);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
return _stlink_usb_read_mem32(sl, addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
|
|
||||||
if (len > 0x40) { // !!! never ever: Writing more then 0x40 bytes gives
|
|
||||||
// unexpected behaviour
|
|
||||||
fprintf(stderr, "Error: Data length > 64: +%d byte.\n", len);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
return _stlink_usb_write_mem8(sl, addr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_write_reg(stlink_t *sl, uint32_t reg, int idx) {
|
|
||||||
return _stlink_usb_write_reg(sl, reg, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
|
|
||||||
if (r_idx > 20 || r_idx < 0) {
|
|
||||||
fprintf(stderr, "Error: register index must be in [0..20]\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _stlink_usb_read_reg(sl, r_idx, regp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stlink_is_core_halted(stlink_t *sl) {
|
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
stlink_status(sl);
|
|
||||||
if (sl->q_buf[0] == STLINK_CORE_HALTED) ret = true;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_step(stlink_t *sl) {
|
|
||||||
return _stlink_usb_step(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_current_mode(stlink_t *sl) {
|
|
||||||
return _stlink_usb_current_mode(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of delegates.... Common code below here...
|
|
||||||
|
|
||||||
// Endianness
|
|
||||||
// http://www.ibm.com/developerworks/aix/library/au-endianc/index.html
|
|
||||||
// const int i = 1;
|
|
||||||
// #define is_bigendian() ( (*(char*)&i) == 0 )
|
|
||||||
|
|
||||||
unsigned int is_bigendian(void) {
|
|
||||||
static volatile const unsigned int i = 1;
|
|
||||||
return *(volatile const char *) &i == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t read_uint16(const unsigned char *c, const int pt) {
|
|
||||||
uint32_t ui;
|
|
||||||
char *p = (char *) &ui;
|
|
||||||
|
|
||||||
if (!is_bigendian()) { // le -> le (don't swap)
|
|
||||||
p[0] = c[pt + 0];
|
|
||||||
p[1] = c[pt + 1];
|
|
||||||
} else {
|
|
||||||
p[0] = c[pt + 1];
|
|
||||||
p[1] = c[pt + 0];
|
|
||||||
}
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
// same as above with entrypoint.
|
|
||||||
|
|
||||||
void stlink_run_at(stlink_t *sl, stm32_addr_t addr) {
|
|
||||||
stlink_write_reg(sl, addr, 15); /* pc register */
|
|
||||||
|
|
||||||
stlink_run(sl);
|
|
||||||
|
|
||||||
while (stlink_is_core_halted(sl)) usleep(3000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stlink_core_stat(stlink_t *sl) {
|
|
||||||
if (sl->q_len <= 0) return;
|
|
||||||
|
|
||||||
switch (sl->q_buf[0]) {
|
|
||||||
case STLINK_CORE_RUNNING:
|
|
||||||
sl->core_stat = STLINK_CORE_RUNNING;
|
|
||||||
return;
|
|
||||||
case STLINK_CORE_HALTED:
|
|
||||||
sl->core_stat = STLINK_CORE_HALTED;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
|
|
||||||
fprintf(stderr, " core status: unknown\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stlink_fwrite_finalize(stlink_t *sl, stm32_addr_t addr) {
|
|
||||||
unsigned int val;
|
|
||||||
/* set stack*/
|
|
||||||
stlink_read_debug32(sl, addr, &val);
|
|
||||||
stlink_write_reg(sl, val, 13);
|
|
||||||
/* Set PC to the reset routine*/
|
|
||||||
stlink_read_debug32(sl, addr + 4, &val);
|
|
||||||
stlink_write_reg(sl, val, 15);
|
|
||||||
stlink_run(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef bool (*save_block_fn)(void *arg, uint8_t *block, ssize_t len);
|
|
||||||
|
|
||||||
static int stlink_read(stlink_t *sl, stm32_addr_t addr, size_t size,
|
|
||||||
save_block_fn fn, void *fn_arg) {
|
|
||||||
int error = -1;
|
|
||||||
|
|
||||||
if (size < 1) size = sl->flash_size;
|
|
||||||
|
|
||||||
if (size > sl->flash_size) size = sl->flash_size;
|
|
||||||
|
|
||||||
size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz;
|
|
||||||
for (size_t off = 0; off < size; off += cmp_size) {
|
|
||||||
size_t aligned_size;
|
|
||||||
|
|
||||||
/* adjust last page size */
|
|
||||||
if ((off + cmp_size) > size) cmp_size = size - off;
|
|
||||||
|
|
||||||
aligned_size = cmp_size;
|
|
||||||
if (aligned_size & (4 - 1)) aligned_size = (cmp_size + 4) & ~(4 - 1);
|
|
||||||
|
|
||||||
stlink_read_mem32(sl, addr + (uint32_t) off, aligned_size);
|
|
||||||
|
|
||||||
if (!fn(fn_arg, sl->q_buf, aligned_size)) {
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
error = 0;
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_buffer_to_sram(stlink_t *sl, flash_loader_t *fl, const uint8_t *buf,
|
|
||||||
size_t size) {
|
|
||||||
/* write the buffer right after the loader */
|
|
||||||
size_t chunk = size & ~0x3;
|
|
||||||
size_t rem = size & 0x3;
|
|
||||||
if (chunk) {
|
|
||||||
memcpy(sl->q_buf, buf, chunk);
|
|
||||||
stlink_write_mem32(sl, fl->buf_addr, chunk);
|
|
||||||
}
|
|
||||||
if (rem) {
|
|
||||||
memcpy(sl->q_buf, buf + chunk, rem);
|
|
||||||
stlink_write_mem8(sl, (fl->buf_addr) + (uint32_t) chunk, rem);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t calculate_F7_sectornum(uint32_t flashaddr) {
|
|
||||||
flashaddr &= ~STM32_FLASH_BASE; // Page now holding the actual flash address
|
|
||||||
if (flashaddr < 0x20000)
|
|
||||||
return (flashaddr / 0x8000);
|
|
||||||
else if (flashaddr < 0x40000)
|
|
||||||
return (4);
|
|
||||||
else
|
|
||||||
return (flashaddr / 0x40000) + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr) {
|
|
||||||
if (sl->chip_id == STLINK_CHIPID_STM32_F7) {
|
|
||||||
uint32_t sector = calculate_F7_sectornum(flashaddr);
|
|
||||||
if (sector < 4)
|
|
||||||
sl->flash_pgsz = 0x8000;
|
|
||||||
else if (sector < 5)
|
|
||||||
sl->flash_pgsz = 0x20000;
|
|
||||||
else
|
|
||||||
sl->flash_pgsz = 0x40000;
|
|
||||||
}
|
|
||||||
return (uint32_t) sl->flash_pgsz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Erase a page of flash, assumes sl is fully populated with things like
|
|
||||||
* chip/core ids
|
|
||||||
* @param sl stlink context
|
|
||||||
* @param flashaddr an address in the flash page to erase
|
|
||||||
* @return 0 on success -ve on failure
|
|
||||||
*/
|
|
||||||
int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
|
|
||||||
/* wait for ongoing op to finish */
|
|
||||||
wait_flash_busy(sl);
|
|
||||||
|
|
||||||
/* unlock if locked */
|
|
||||||
unlock_flash_if(sl);
|
|
||||||
|
|
||||||
/* select the page to erase */
|
|
||||||
// calculate the actual page from the address
|
|
||||||
uint32_t sector = calculate_F7_sectornum(flashaddr);
|
|
||||||
|
|
||||||
write_flash_cr_snb(sl, sector);
|
|
||||||
|
|
||||||
/* start erase operation */
|
|
||||||
set_flash_cr_strt(sl);
|
|
||||||
|
|
||||||
/* wait for completion */
|
|
||||||
wait_flash_busy(sl);
|
|
||||||
|
|
||||||
/* relock the flash */
|
|
||||||
// todo: fails to program if this is in
|
|
||||||
lock_flash(sl);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify addr..addr+len is binary identical to base...base+len
|
|
||||||
* @param sl stlink context
|
|
||||||
* @param address stm device address
|
|
||||||
* @param data host side buffer to check against
|
|
||||||
* @param length how much
|
|
||||||
* @return 0 for success, -ve for failure
|
|
||||||
*/
|
|
||||||
int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data,
|
|
||||||
unsigned length) {
|
|
||||||
size_t off;
|
|
||||||
size_t cmp_size = (sl->flash_pgsz > 0x1800) ? 0x1800 : sl->flash_pgsz;
|
|
||||||
printf("Verifying flash...\n");
|
|
||||||
for (off = 0; off < length; off += cmp_size) {
|
|
||||||
size_t aligned_size;
|
|
||||||
|
|
||||||
/* adjust last page size */
|
|
||||||
if ((off + cmp_size) > length) cmp_size = length - off;
|
|
||||||
|
|
||||||
aligned_size = cmp_size;
|
|
||||||
if (aligned_size & (4 - 1)) aligned_size = (cmp_size + 4) & ~(4 - 1);
|
|
||||||
|
|
||||||
stlink_read_mem32(sl, address + (uint32_t) off, aligned_size);
|
|
||||||
|
|
||||||
if (memcmp(sl->q_buf, data + off, cmp_size)) {
|
|
||||||
printf("Verification of flash failed at offset: %u\n",
|
|
||||||
(unsigned int) off);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base,
|
|
||||||
uint32_t len, uint8_t eraseonly) {
|
|
||||||
size_t off;
|
|
||||||
flash_loader_t fl;
|
|
||||||
printf("Writing %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr,
|
|
||||||
addr);
|
|
||||||
/* check addr range is inside the flash */
|
|
||||||
stlink_calculate_pagesize(sl, addr);
|
|
||||||
if (addr < sl->flash_base) {
|
|
||||||
printf("addr too low %#x < %#x\n", addr, sl->flash_base);
|
|
||||||
return -1;
|
|
||||||
} else if ((addr + len) < addr) {
|
|
||||||
printf("addr overruns\n");
|
|
||||||
return -1;
|
|
||||||
} else if ((addr + len) > (sl->flash_base + sl->flash_size)) {
|
|
||||||
printf("addr too high\n");
|
|
||||||
return -1;
|
|
||||||
} else if (addr & 1) {
|
|
||||||
printf("unaligned addr 0x%x\n", addr);
|
|
||||||
return -1;
|
|
||||||
} else if (len & 1) {
|
|
||||||
printf("unaligned len 0x%x -- padding with zero\n", len);
|
|
||||||
len += 1;
|
|
||||||
} else if (addr & (sl->flash_pgsz - 1)) {
|
|
||||||
printf("addr not a multiple of pagesize, not supported\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we've loaded the context with the chip details
|
|
||||||
stlink_core_id(sl);
|
|
||||||
/* erase each page */
|
|
||||||
int page_count = 0;
|
|
||||||
for (off = 0; off < len;
|
|
||||||
off += stlink_calculate_pagesize(sl, addr + (uint32_t) off)) {
|
|
||||||
fprintf(stdout, "Erasing flash page at addr 0x%08X\n", (int) (addr + off));
|
|
||||||
/* addr must be an addr inside the page */
|
|
||||||
if (stlink_erase_flash_page(sl, addr + (uint32_t) off) == -1) {
|
|
||||||
printf("Failed to erase_flash_page(%#zx) == -1\n", addr + off);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
page_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eraseonly) return 0;
|
|
||||||
|
|
||||||
/* flash loader initialization */
|
|
||||||
if (stlink_flash_loader_init(sl, &fl) == -1) {
|
|
||||||
printf("stlink_flash_loader_init() == -1\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First unlock the cr */
|
|
||||||
unlock_flash_if(sl);
|
|
||||||
|
|
||||||
/* TODO: Check that Voltage range is 2.7 - 3.6 V */
|
|
||||||
/* set parallelisim to 32 bit*/
|
|
||||||
int voltage = stlink_target_voltage(sl);
|
|
||||||
if (voltage == -1) {
|
|
||||||
printf("Failed to read Target voltage\n");
|
|
||||||
return voltage;
|
|
||||||
} else if (voltage > 2700) {
|
|
||||||
write_flash_cr_psiz(sl, 2);
|
|
||||||
} else {
|
|
||||||
printf(
|
|
||||||
"Target voltage (%d mV) too low for 32-bit flash, using 8-bit "
|
|
||||||
"flash writes\n",
|
|
||||||
voltage);
|
|
||||||
write_flash_cr_psiz(sl, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set programming mode */
|
|
||||||
set_flash_cr_pg(sl);
|
|
||||||
|
|
||||||
for (off = 0; off < len;) {
|
|
||||||
size_t size = len - off > 0x8000 ? 0x8000 : len - off;
|
|
||||||
printf("Writing %d bytes at 0x%08X\n", (int) size,
|
|
||||||
(int) (addr + (uint32_t) off));
|
|
||||||
if (stlink_flash_loader_run(sl, &fl, addr + (uint32_t) off, base + off,
|
|
||||||
size) == -1) {
|
|
||||||
printf("stlink_flash_loader_run(%#zx) failed! == -1\n", addr + off);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
off += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Relock flash */
|
|
||||||
lock_flash(sl);
|
|
||||||
|
|
||||||
return stlink_verify_write_flash(sl, addr, base, len);
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/* simple wrapper around the stlink_flash_write function */
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include "stlink.h"
|
|
||||||
#include "usb.h"
|
|
||||||
|
|
||||||
#define FLASH_ADDRESS 0x8000000
|
|
||||||
|
|
||||||
int stm32_flash(const char *device_name, void *data, int len) {
|
|
||||||
stlink_t *sl = NULL;
|
|
||||||
int err = -1;
|
|
||||||
uint8_t serial[16];
|
|
||||||
|
|
||||||
int j = (int) strlen(device_name);
|
|
||||||
int length = j / 2; // the length of the destination-array
|
|
||||||
if (j % 2 != 0) return -1;
|
|
||||||
|
|
||||||
for (size_t k = 0; j >= 0 && k < sizeof(serial); ++k, j -= 2) {
|
|
||||||
char buffer[3] = {0};
|
|
||||||
memcpy(buffer, device_name + j, 2);
|
|
||||||
serial[length - k] = (uint8_t) strtol(buffer, NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
sl = stlink_open_usb(1, (char *) serial);
|
|
||||||
|
|
||||||
if (sl == NULL) return -1;
|
|
||||||
|
|
||||||
if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
|
|
||||||
if (stlink_exit_dfu_mode(sl)) {
|
|
||||||
printf("Failed to exit DFU mode\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) {
|
|
||||||
if (stlink_enter_swd_mode(sl)) {
|
|
||||||
printf("Failed to enter SWD mode\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stlink_jtag_reset(sl, 2)) {
|
|
||||||
printf("Failed to reset JTAG\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stlink_reset(sl)) {
|
|
||||||
printf("Failed to reset device\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Core must be halted to use RAM based flashloaders
|
|
||||||
if (stlink_force_debug(sl)) {
|
|
||||||
printf("Failed to halt the core\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stlink_status(sl)) {
|
|
||||||
printf("Failed to get Core's status\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
if ((FLASH_ADDRESS > sl->flash_base + sl->flash_size)) {
|
|
||||||
printf("Unknown memory region\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = stlink_write_flash(sl, FLASH_ADDRESS, (uint8_t *) data, len, 0);
|
|
||||||
stlink_fwrite_finalize(sl, FLASH_ADDRESS);
|
|
||||||
|
|
||||||
if (err == -1) {
|
|
||||||
printf("stlink_fwrite_flash() == -1\n");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
stlink_jtag_reset(sl, 2);
|
|
||||||
stlink_reset(sl);
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
stlink_exit_debug_mode(sl);
|
|
||||||
stlink_close(sl);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
Loaded 100 of 146 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user