diff --git a/README.md b/README.md index 17bbfe45aac44b56742f655534982507fb0824d4..5235006919355f2abac20f9e43956fedf50401d3 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operatin # Support - [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) -- [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) - [Check our latest releases](https://github.com/cesanta/mongoose/releases) diff --git a/mongoose.c b/mongoose.c index 9026762e34ae0c32fc1cd2ab63c09f17b0692e07..9571d57493d09265b90187e6a3f30b149809df19 100644 --- a/mongoose.c +++ b/mongoose.c @@ -88,6 +88,9 @@ extern void *(*test_calloc)(size_t count, size_t size); #if MG_ENABLE_HTTP struct mg_serve_http_opts; +MG_INTERNAL struct mg_http_proto_data *mg_http_create_proto_data( + struct mg_connection *c); + /* * Reassemble the content of the buffer (buf, blen) which should be * in the HTTP chunked encoding, by collapsing data chunks to the @@ -2705,8 +2708,8 @@ static int mg_resolve2(const char *host, struct in_addr *ina) { return 0; } for (p = servinfo; p != NULL; p = p->ai_next) { - memcpy(&h, &p->ai_addr, sizeof(struct sockaddr_in *)); - memcpy(ina, &h->sin_addr, sizeof(ina)); + memcpy(&h, &p->ai_addr, sizeof(h)); + memcpy(ina, &h->sin_addr, sizeof(*ina)); } freeaddrinfo(servinfo); return 1; @@ -3241,6 +3244,16 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address, return mg_connect_opt(mgr, address, MG_CB(callback, user_data), opts); } +void mg_ev_handler_empty(struct mg_connection *c, int ev, + void *ev_data MG_UD_ARG(void *user_data)) { + (void) c; + (void) ev; + (void) ev_data; +#if MG_ENABLE_CALLBACK_USERDATA + (void) user_data; +#endif +} + struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data), @@ -3252,6 +3265,8 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts); + if (callback == NULL) callback = mg_ev_handler_empty; + if ((nc = mg_create_connection(mgr, callback, add_sock_opts)) == NULL) { return NULL; } @@ -3365,10 +3380,7 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, opts.user_data = user_data; #endif - if (callback == NULL) { - MG_SET_PTRPTR(opts.error_string, "handler is required"); - return NULL; - } + if (callback == NULL) callback = mg_ev_handler_empty; MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts); @@ -4956,7 +4968,7 @@ static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx, const char *cl) { : MG_SSL_ERROR); } -#ifndef KR_VERSION +#if !defined(KR_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) static unsigned int mg_ssl_if_ossl_psk_cb(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, @@ -5022,10 +5034,10 @@ static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(struct mg_ssl_if_ctx *ctx, (void) ctx; (void) identity; (void) key_str; - /* Krypton does not support PSK. */ + /* Krypton / LibreSSL does not support PSK. */ return MG_SSL_ERROR; } -#endif /* defined(KR_VERSION) */ +#endif /* !defined(KR_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) */ const char *mg_set_ssl(struct mg_connection *nc, const char *cert, const char *ca_cert) { @@ -5999,20 +6011,29 @@ struct mg_http_proto_data { size_t rcvd; /* How many bytes we have received. */ }; -static void mg_http_conn_destructor(void *proto_data); +static void mg_http_proto_data_destructor(void *proto_data); + struct mg_connection *mg_connect_http_base( struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data), struct mg_connect_opts opts, const char *scheme1, const char *scheme2, const char *scheme_ssl1, const char *scheme_ssl2, const char *url, struct mg_str *path, struct mg_str *user_info, struct mg_str *host); -static struct mg_http_proto_data *mg_http_get_proto_data( +MG_INTERNAL struct mg_http_proto_data *mg_http_create_proto_data( struct mg_connection *c) { - if (c->proto_data == NULL) { - c->proto_data = MG_CALLOC(1, sizeof(struct mg_http_proto_data)); - c->proto_data_destructor = mg_http_conn_destructor; - } + /* If we have proto data from previous connection, flush it. */ + if (c->proto_data != NULL) { + void *pd = c->proto_data; + c->proto_data = NULL; + mg_http_proto_data_destructor(pd); + } + c->proto_data = MG_CALLOC(1, sizeof(struct mg_http_proto_data)); + c->proto_data_destructor = mg_http_proto_data_destructor; + return (struct mg_http_proto_data *) c->proto_data; +} +static struct mg_http_proto_data *mg_http_get_proto_data( + struct mg_connection *c) { return (struct mg_http_proto_data *) c->proto_data; } @@ -6068,7 +6089,7 @@ static void mg_http_free_reverse_proxy_data(struct mg_reverse_proxy_data *rpd) { } } -static void mg_http_conn_destructor(void *proto_data) { +static void mg_http_proto_data_destructor(void *proto_data) { struct mg_http_proto_data *pd = (struct mg_http_proto_data *) proto_data; #if MG_ENABLE_FILESYSTEM mg_http_free_proto_data_file(&pd->file); @@ -6341,7 +6362,8 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) { /* Rate-limited */ } if (pd->file.sent >= pd->file.cl) { - LOG(LL_DEBUG, ("%p done, %d bytes", nc, (int) pd->file.sent)); + LOG(LL_DEBUG, ("%p done, %d bytes, ka %d", nc, (int) pd->file.sent, + pd->file.keepalive)); if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE; mg_http_free_proto_data_file(&pd->file); } @@ -6477,12 +6499,12 @@ struct mg_http_endpoint *mg_http_get_endpoint_handler(struct mg_connection *nc, int matched, matched_max = 0; struct mg_http_endpoint *ep; - if (nc == NULL) { - return NULL; - } + if (nc == NULL) return NULL; pd = mg_http_get_proto_data(nc); + if (pd == NULL) return NULL; + ep = pd->endpoints; while (ep != NULL) { if ((matched = mg_match_prefix_n(ep->uri_pattern, *uri_path)) > 0) { @@ -6554,13 +6576,13 @@ void mg_http_handler(struct mg_connection *nc, int ev, if (ev == MG_EV_CLOSE) { #if MG_ENABLE_HTTP_CGI /* Close associated CGI forwarder connection */ - if (pd->cgi.cgi_nc != NULL) { + if (pd != NULL && pd->cgi.cgi_nc != NULL) { pd->cgi.cgi_nc->user_data = NULL; pd->cgi.cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY; } #endif #if MG_ENABLE_HTTP_STREAMING_MULTIPART - if (pd->mp_stream.boundary != NULL) { + if (pd != NULL && pd->mp_stream.boundary != NULL) { /* * Multipart message is in progress, but connection is closed. * Finish part and request with an error flag. @@ -6590,14 +6612,14 @@ void mg_http_handler(struct mg_connection *nc, int ev, deliver_chunk(nc, hm, req_len); mg_http_call_endpoint_handler(nc, ev2, hm); } - pd->rcvd = 0; - if (pd->endpoint_handler != NULL && pd->endpoint_handler != nc->handler) { + if (pd != NULL && pd->endpoint_handler != NULL && + pd->endpoint_handler != nc->handler) { mg_call(nc, pd->endpoint_handler, nc->user_data, ev, NULL); } } #if MG_ENABLE_FILESYSTEM - if (pd->file.fp != NULL) { + if (pd != NULL && pd->file.fp != NULL) { mg_http_transfer_file_data(nc); } #endif @@ -6605,7 +6627,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, mg_call(nc, nc->handler, nc->user_data, ev, ev_data); #if MG_ENABLE_HTTP_STREAMING_MULTIPART - if (pd->mp_stream.boundary != NULL && + if (pd != NULL && pd->mp_stream.boundary != NULL && (ev == MG_EV_RECV || ev == MG_EV_POLL)) { if (ev == MG_EV_RECV) { pd->rcvd += *(int *) ev_data; @@ -6620,11 +6642,16 @@ void mg_http_handler(struct mg_connection *nc, int ev, if (ev == MG_EV_RECV) { struct mg_str *s; - pd->rcvd += *(int *) ev_data; again: req_len = mg_parse_http(io->buf, io->len, hm, is_req); + if (req_len > 0) { + /* New request - new proto data */ + pd = mg_http_create_proto_data(nc); + pd->rcvd = io->len; + } + if (req_len > 0 && (s = mg_get_http_header(hm, "Transfer-Encoding")) != NULL && mg_vcasecmp(s, "chunked") == 0) { @@ -6736,18 +6763,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, /* If this is a CGI request, we are not done either. */ if (pd->cgi.cgi_nc != NULL) request_done = 0; #endif - if (request_done) { - /* This request is done but we may receive another on this connection. - */ - mg_http_conn_destructor(pd); - nc->proto_data = NULL; - if (io->len > 0) { - /* We already have data for the next one, restart parsing. */ - pd = mg_http_get_proto_data(nc); - pd->rcvd = io->len; - goto again; - } - } + if (request_done && io->len > 0) goto again; } } } @@ -8887,6 +8903,7 @@ void mg_register_http_endpoint_opt(struct mg_connection *nc, if (new_ep == NULL) return; pd = mg_http_get_proto_data(nc); + if (pd == NULL) pd = mg_http_create_proto_data(nc); new_ep->uri_pattern = mg_strdup(mg_mk_str(uri_path)); if (opts.auth_domain != NULL && opts.auth_file != NULL) { new_ep->auth_domain = strdup(opts.auth_domain); @@ -10824,7 +10841,7 @@ static const char *scanto(const char *p, struct mg_str *s) { MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { uint8_t header; size_t len = 0, len_len = 0; - const char *p, *end; + const char *p, *end, *eop = &io->buf[io->len]; unsigned char lc = 0; int cmd; @@ -10835,7 +10852,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { /* decode mqtt variable length */ len = len_len = 0; p = io->buf + 1; - while ((size_t)(p - io->buf) < io->len) { + while (p < eop) { lc = *((const unsigned char *) p++); len += (lc & 0x7f) << 7 * len_len; len_len++; @@ -10844,9 +10861,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { } end = p + len; - if (lc & 0x80 || len > (io->len - (p - io->buf))) { - return MG_MQTT_ERROR_INCOMPLETE_MSG; - } + if (lc & 0x80 || end > eop) return MG_MQTT_ERROR_INCOMPLETE_MSG; mm->cmd = cmd; mm->qos = MG_MQTT_GET_QOS(header); @@ -10900,7 +10915,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { case MG_MQTT_CMD_PUBREL: case MG_MQTT_CMD_PUBCOMP: case MG_MQTT_CMD_SUBACK: + if (end - p < 2) return MG_MQTT_ERROR_MALFORMED_MSG; mm->message_id = getu16(p); + p += 2; break; case MG_MQTT_CMD_PUBLISH: { p = scanto(p, &mm->topic); @@ -15214,7 +15231,8 @@ void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr); #include <lwip/tcp.h> #include <lwip/tcpip.h> #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 #include <lwip/tcp_impl.h> #endif @@ -15254,9 +15272,35 @@ void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr); #define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr #endif -#if NO_SYS -#define tcpip_callback(fn, arg) (fn)(arg) -typedef void (*tcpip_callback_fn)(void *arg); +#if !NO_SYS +#if LWIP_TCPIP_CORE_LOCKING +/* 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 void mg_lwip_if_init(struct mg_iface *iface); @@ -15265,7 +15309,8 @@ void mg_lwip_if_add_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); -#if defined(RTOS_SDK) || defined(ESP_PLATFORM) +// If compiling for Mongoose OS. +#ifdef MGOS extern void mgos_lock(); extern void mgos_unlock(); #else @@ -15434,7 +15479,7 @@ static void mg_lwip_if_connect_tcp_tcpip(void *arg) { void mg_lwip_if_connect_tcp(struct mg_connection *nc, const union socket_address *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); } /* @@ -15527,7 +15572,7 @@ static void mg_lwip_if_connect_udp_tcpip(void *arg) { } 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); } static void tcp_close_tcpip(void *arg) { @@ -15613,7 +15658,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) { 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; } @@ -15639,7 +15684,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) { 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; } @@ -15664,7 +15709,7 @@ static void mg_lwip_tcp_write_tcpip(void *arg) { if (len == 0) { DBG(("%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); - tcpip_callback(tcp_output_tcpip, tpcb); + mg_lwip_netif_run_on_tcpip(tcp_output_tcpip, tpcb); ctx->ret = 0; return; } @@ -15707,7 +15752,7 @@ int mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) { struct tcp_pcb *tpcb = cs->pcb.tcp; if (tpcb == NULL) return -1; if (tpcb->snd_buf <= 0) return 0; - tcpip_callback(mg_lwip_tcp_write_tcpip, &ctx); + mg_lwip_netif_run_on_tcpip(mg_lwip_tcp_write_tcpip, &ctx); return ctx.ret; } @@ -15739,7 +15784,7 @@ static int mg_lwip_if_udp_send(struct mg_connection *nc, const void *data, if (p == NULL) return 0; memcpy(p->payload, data, len); 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; pbuf_free(p); return (cs->err == ERR_OK ? (int) len : -2); @@ -15800,7 +15845,7 @@ static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf, mgos_unlock(); if (res > 0) { struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = res}; - tcpip_callback(tcp_recved_tcpip, &ctx); + mg_lwip_netif_run_on_tcpip(tcp_recved_tcpip, &ctx); } return res; } @@ -15827,7 +15872,7 @@ void mg_lwip_if_destroy_conn(struct mg_connection *nc) { tcp_arg(tpcb, NULL); DBG(("%p tcp_close %p", nc, tpcb)); 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) { struct pbuf *seg = cs->rx_chain; @@ -15841,7 +15886,7 @@ void mg_lwip_if_destroy_conn(struct mg_connection *nc) { struct udp_pcb *upcb = cs->pcb.udp; if (upcb != NULL) { 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)); MG_FREE(cs); @@ -16002,6 +16047,10 @@ void mg_lwip_if_init(struct mg_iface *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)); +#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) { @@ -16043,7 +16092,7 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { if (nc->sock != INVALID_SOCKET && !(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != 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 (num_timers == 0 || nc->ev_timer_time < min_timer) { diff --git a/mongoose.h b/mongoose.h index 0f85b18b61b5289dc471fc32ad38b0f2966fe8a2..28d628555678f30ce2f04b92db8f220b3533b491 100644 --- a/mongoose.h +++ b/mongoose.h @@ -58,8 +58,9 @@ #define CS_P_NRF51 12 #define CS_P_NRF52 10 #define CS_P_PIC32 11 +#define CS_P_RS14100 18 #define CS_P_STM32 16 -/* Next id: 18 */ +/* Next id: 19 */ /* If not specified explicitly, we guess platform by defines. */ #ifndef CS_PLATFORM @@ -91,6 +92,8 @@ #elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) #define CS_PLATFORM CS_P_TM4C129 +#elif defined(RS14100) +#define CS_PLATFORM CS_P_RS14100 #elif defined(STM32) #define CS_PLATFORM CS_P_STM32 #endif @@ -125,7 +128,11 @@ /* Amalgamated: #include "common/platforms/platform_nxp_lpc.h" */ /* Amalgamated: #include "common/platforms/platform_nxp_kinetis.h" */ /* Amalgamated: #include "common/platforms/platform_pic32.h" */ +/* Amalgamated: #include "common/platforms/platform_rs14100.h" */ /* Amalgamated: #include "common/platforms/platform_stm32.h" */ +#if CS_PLATFORM == CS_P_CUSTOM +#include <platform_custom.h> +#endif /* Common stuff */ @@ -1907,6 +1914,70 @@ char *inet_ntoa(struct in_addr in); #endif /* CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_ */ #ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_rs14100.h" +#endif +/* + * 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_ */ +#ifdef MG_MODULE_LINES #line 1 "common/platforms/platform_stm32.h" #endif /* diff --git a/src/common/platform.h b/src/common/platform.h index af0b4f501b05a23721ed49a91390fa8e14b8d433..af91973fb63a4bd854ed32e8963043345e8e0edf 100644 --- a/src/common/platform.h +++ b/src/common/platform.h @@ -22,8 +22,9 @@ #define CS_P_NRF51 12 #define CS_P_NRF52 10 #define CS_P_PIC32 11 +#define CS_P_RS14100 18 #define CS_P_STM32 16 -/* Next id: 18 */ +/* Next id: 19 */ /* If not specified explicitly, we guess platform by defines. */ #ifndef CS_PLATFORM @@ -55,6 +56,8 @@ #elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) #define CS_PLATFORM CS_P_TM4C129 +#elif defined(RS14100) +#define CS_PLATFORM CS_P_RS14100 #elif defined(STM32) #define CS_PLATFORM CS_P_STM32 #endif @@ -89,7 +92,11 @@ #include "common/platforms/platform_nxp_lpc.h" #include "common/platforms/platform_nxp_kinetis.h" #include "common/platforms/platform_pic32.h" +#include "common/platforms/platform_rs14100.h" #include "common/platforms/platform_stm32.h" +#if CS_PLATFORM == CS_P_CUSTOM +#include <platform_custom.h> +#endif /* Common stuff */ diff --git a/src/common/platforms/arm/arm_exc.c b/src/common/platforms/arm/arm_exc.c index 606ae5ebbe1a6f64d4123dec274f5b7dbb933655..3477e6bf3c10f7c4925071d34b16219546271620 100644 --- a/src/common/platforms/arm/arm_exc.c +++ b/src/common/platforms/arm/arm_exc.c @@ -15,6 +15,8 @@ * limitations under the License. */ +#include "arm_exc.h" + #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -31,33 +33,7 @@ #define MGOS_ENABLE_CORE_DUMP 1 #endif -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; -#ifdef ARM_HAVE_FPU - 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 cpsr; - uint64_t d[16]; - uint32_t fpscr; -} __attribute__((packed)); - -#if ARM_HAVE_FPU && !defined(MGOS_BOOT_BUILD) +#if __FPU_PRESENT && !defined(MGOS_BOOT_BUILD) static void save_s16_s31(uint32_t *dst) { __asm volatile( "\ @@ -91,17 +67,25 @@ static void print_fpu_regs(const uint32_t *regs, int off, int n) { } #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, struct arm_gdb_reg_file *rf) { char buf[8]; const char *name; - (void) ef; +#if __MPU_PRESENT + MPU->CTRL = 0; // Disable MPU. +#endif portDISABLE_INTERRUPTS(); + s_rf = rf; switch (isr_no) { case 0: name = "ThreadMode"; break; - case 1: case 7: case 8: @@ -110,7 +94,6 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, case 13: name = "Reserved"; break; - case 2: name = "NMI"; break; @@ -155,12 +138,14 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, 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", 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); - 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)); -#if ARM_HAVE_FPU && !defined(MGOS_BOOT_BUILD) +#if !defined(MGOS_BOOT_BUILD) rf->fpscr = ef->fpscr; memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s)); print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s)); @@ -173,11 +158,9 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, #else rf->fpscr = 0; #endif +#endif #if MGOS_ENABLE_CORE_DUMP - mgos_cd_emit_header(); - mgos_cd_emit_section(MGOS_CORE_DUMP_SECTION_REGS, rf, sizeof(*rf)); - mgos_cd_emit_section("SRAM", (void *) SRAM_BASE_ADDR, SRAM_SIZE); - mgos_cd_emit_footer(); + mgos_cd_write(); #endif #ifdef MGOS_HALT_ON_EXCEPTION mgos_cd_printf("Halting\n"); @@ -188,4 +171,5 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, mgos_cd_printf("Rebooting\n"); mgos_dev_system_restart(); #endif + (void) ef; } diff --git a/src/common/platforms/arm/arm_exc.h b/src/common/platforms/arm/arm_exc.h new file mode 100644 index 0000000000000000000000000000000000000000..63a2c1ccbbbdea910a98eaab446457de9046fb25 --- /dev/null +++ b/src/common/platforms/arm/arm_exc.h @@ -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); diff --git a/src/common/platforms/arm/arm_exc_top.S b/src/common/platforms/arm/arm_exc_top.S index 9ffade47e48f07648db9b1e069eb9fdfb7184bc7..10a7c9ae5a579ecf88ef813196b96e49db1f43ca 100644 --- a/src/common/platforms/arm/arm_exc_top.S +++ b/src/common/platforms/arm/arm_exc_top.S @@ -28,12 +28,12 @@ arm_exc_handler_top: mrseq r1, msp mrsne r1, psp // 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) - sub sp, #328 // sizeof(arm_gdb_reg_file) + sub sp, #208 // sizeof(arm_gdb_reg_file) #else 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 mov r2, sp // r0 -> original sp, r2 -> arm_gdb_reg_file to fill @@ -63,6 +63,17 @@ arm_exc_handler_top: str r3, [r2, #60] ldr r3, [r1, #28] // xpsr 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 b arm_exc_handler_bottom diff --git a/src/common/platforms/arm/arm_nsleep100_m3.S b/src/common/platforms/arm/arm_nsleep100_m3.S index cae920e3c4e5c96d723255fe7fdaad40017678a0..0ce16bf52d7ef49a4c66143e99ccc1d9b412b36f 100644 --- a/src/common/platforms/arm/arm_nsleep100_m3.S +++ b/src/common/platforms/arm/arm_nsleep100_m3.S @@ -26,11 +26,7 @@ .global mgos_nsleep100_impl .global mgos_nsleep100_loop_count -#ifdef STM32 -.section .RamFunc.mgos_nsleep100_impl -#else -.section .iram.mgos_nsleep100_impl -#endif +.section .text.IRAM.mgos_nsleep100_impl .type mgos_nsleep100_impl, %function .align 4 diff --git a/src/common/platforms/arm/arm_nsleep100_m4.S b/src/common/platforms/arm/arm_nsleep100_m4.S index afb596fafae5986e0b78a75f859f2b49db445777..45cc32b30ebb8822cda8433b7c6bea6e2036e785 100644 --- a/src/common/platforms/arm/arm_nsleep100_m4.S +++ b/src/common/platforms/arm/arm_nsleep100_m4.S @@ -26,10 +26,10 @@ .global mgos_nsleep100_impl .global mgos_nsleep100_loop_count -#ifdef STM32 -.section .RamFunc.mgos_nsleep100_impl -#else +#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 @@ -38,17 +38,17 @@ mgos_nsleep100_impl: ldr r3, =mgos_nsleep100_loop_count ldr r3, [r3] mul r0, r3 -#ifdef STM32L4 +#if defined(STM32L4) mov r1, #3 #else mov r1, #6 #endif udiv r0, r0, r1 - cbz r0, xxx -lxx: + cbz r0, mgos_nsleep100_impl_out +mgos_nsleep100_impl_loop: subs r0, #1 - bne lxx -xxx: + bne mgos_nsleep100_impl_loop +mgos_nsleep100_impl_out: bx lr .align 4 .size mgos_nsleep100_impl, . - mgos_nsleep100_impl diff --git a/src/common/platforms/arm/arm_nsleep100_m7.S b/src/common/platforms/arm/arm_nsleep100_m7.S index 36c878fdb2bbccd279063d9ca30ba15e7f1125df..be6da6f7b536533bcb242e36435eaf01f011f4df 100644 --- a/src/common/platforms/arm/arm_nsleep100_m7.S +++ b/src/common/platforms/arm/arm_nsleep100_m7.S @@ -26,11 +26,7 @@ .global mgos_nsleep100_impl .global mgos_nsleep100_loop_count -#ifdef STM32 -.section .RamFunc.mgos_nsleep100_impl -#else -.section .iram.mgos_nsleep100_impl -#endif +.section .text.IRAM.mgos_nsleep100_impl .type mgos_nsleep100_impl, %function .align 4 diff --git a/src/common/platforms/lwip/mg_lwip_ev_mgr.c b/src/common/platforms/lwip/mg_lwip_ev_mgr.c index ab8f19f7830b260607d6335423b33fe8daa751f4..afff2dbd281d91d7aa79ff4cebc8b9a4f933f23f 100644 --- a/src/common/platforms/lwip/mg_lwip_ev_mgr.c +++ b/src/common/platforms/lwip/mg_lwip_ev_mgr.c @@ -91,6 +91,10 @@ void mg_lwip_if_init(struct mg_iface *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)); +#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) { @@ -132,7 +136,7 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { if (nc->sock != INVALID_SOCKET && !(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != 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 (num_timers == 0 || nc->ev_timer_time < min_timer) { diff --git a/src/common/platforms/lwip/mg_lwip_net_if.c b/src/common/platforms/lwip/mg_lwip_net_if.c index e78d93cea598e37136ea4b012c7b4851253283a3..754ac2dfa386cb52fffa4901cdfdc16c93a54503 100644 --- a/src/common/platforms/lwip/mg_lwip_net_if.c +++ b/src/common/platforms/lwip/mg_lwip_net_if.c @@ -24,7 +24,8 @@ #include <lwip/tcp.h> #include <lwip/tcpip.h> #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 #include <lwip/tcp_impl.h> #endif @@ -64,9 +65,35 @@ #define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr #endif -#if NO_SYS -#define tcpip_callback(fn, arg) (fn)(arg) -typedef void (*tcpip_callback_fn)(void *arg); +#if !NO_SYS +#if LWIP_TCPIP_CORE_LOCKING +/* 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 void mg_lwip_if_init(struct mg_iface *iface); @@ -75,7 +102,8 @@ void mg_lwip_if_add_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); -#if defined(RTOS_SDK) || defined(ESP_PLATFORM) +// If compiling for Mongoose OS. +#ifdef MGOS extern void mgos_lock(); extern void mgos_unlock(); #else @@ -244,7 +272,7 @@ static void mg_lwip_if_connect_tcp_tcpip(void *arg) { void mg_lwip_if_connect_tcp(struct mg_connection *nc, const union socket_address *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); } /* @@ -337,7 +365,7 @@ static void mg_lwip_if_connect_udp_tcpip(void *arg) { } 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); } static void tcp_close_tcpip(void *arg) { @@ -423,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) { 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; } @@ -449,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) { 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; } @@ -474,7 +502,7 @@ static void mg_lwip_tcp_write_tcpip(void *arg) { if (len == 0) { DBG(("%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); - tcpip_callback(tcp_output_tcpip, tpcb); + mg_lwip_netif_run_on_tcpip(tcp_output_tcpip, tpcb); ctx->ret = 0; return; } @@ -517,7 +545,7 @@ int mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) { struct tcp_pcb *tpcb = cs->pcb.tcp; if (tpcb == NULL) return -1; if (tpcb->snd_buf <= 0) return 0; - tcpip_callback(mg_lwip_tcp_write_tcpip, &ctx); + mg_lwip_netif_run_on_tcpip(mg_lwip_tcp_write_tcpip, &ctx); return ctx.ret; } @@ -549,7 +577,7 @@ static int mg_lwip_if_udp_send(struct mg_connection *nc, const void *data, if (p == NULL) return 0; memcpy(p->payload, data, len); 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; pbuf_free(p); return (cs->err == ERR_OK ? (int) len : -2); @@ -610,7 +638,7 @@ static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf, mgos_unlock(); if (res > 0) { struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = res}; - tcpip_callback(tcp_recved_tcpip, &ctx); + mg_lwip_netif_run_on_tcpip(tcp_recved_tcpip, &ctx); } return res; } @@ -637,7 +665,7 @@ void mg_lwip_if_destroy_conn(struct mg_connection *nc) { tcp_arg(tpcb, NULL); DBG(("%p tcp_close %p", nc, tpcb)); 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) { struct pbuf *seg = cs->rx_chain; @@ -651,7 +679,7 @@ void mg_lwip_if_destroy_conn(struct mg_connection *nc) { struct udp_pcb *upcb = cs->pcb.udp; if (upcb != NULL) { 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)); MG_FREE(cs); diff --git a/src/common/platforms/platform_rs14100.h b/src/common/platforms/platform_rs14100.h new file mode 100644 index 0000000000000000000000000000000000000000..5e9618e572a8d4288e247d72c983dabe47f07109 --- /dev/null +++ b/src/common/platforms/platform_rs14100.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_ */ diff --git a/src/common/platforms/stm32/LICENSE b/src/common/platforms/stm32/LICENSE deleted file mode 100644 index 3d464ca1e3106eb6af66f6baf5f1f921cb6d8604..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/LICENSE +++ /dev/null @@ -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. diff --git a/src/common/platforms/stm32/common.c b/src/common/platforms/stm32/common.c deleted file mode 100644 index 9a201cafde33b00b23e6866b4e1dd58524c8a907..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/common.c +++ /dev/null @@ -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); -} diff --git a/src/common/platforms/stm32/flash.c b/src/common/platforms/stm32/flash.c deleted file mode 100644 index 371c6eb1ac46f0aa405e734a0e81c6dda9b19382..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/flash.c +++ /dev/null @@ -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; -} diff --git a/src/common/platforms/stm32/flash_loader.c b/src/common/platforms/stm32/flash_loader.c deleted file mode 100644 index b508e8e2b27d770938f3be4e3d3991da349f12fa..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/flash_loader.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "stlink.h" - -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -static const uint8_t loader_code_stm32f7[] = { - 0x08, 0x4b, 0x72, 0xb1, 0x04, 0x68, 0x0c, 0x60, - 0xbf, 0xf3, 0x4f, 0x8f, // DSB Memory barrier for in order flash write - 0xdc, 0x89, 0x14, 0xf0, 0x01, 0x0f, 0xfb, 0xd1, - 0x00, 0xf1, 0x04, 0x00, 0x01, 0xf1, 0x04, 0x01, - 0xa2, 0xf1, 0x01, 0x02, 0xef, 0xe7, 0x00, 0xbe, // bkpt #0x00 - 0x00, 0x3c, 0x02, 0x40, -}; - -#define WAIT_ROUNDS 10000 - -int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl) { - size_t size; - - /* allocate the loader in sram */ - if (stlink_flash_loader_write_to_sram(sl, &fl->loader_addr, &size) == -1) { - printf("Failed to write flash loader to sram!\n"); - return -1; - } - - /* allocate a one page buffer in sram right after loader */ - fl->buf_addr = fl->loader_addr + (uint32_t) size; - - return 0; -} - -int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t *addr, - size_t *size) { - memcpy(sl->q_buf, loader_code_stm32f7, sizeof(loader_code_stm32f7)); - stlink_write_mem32(sl, sl->sram_base, sizeof(loader_code_stm32f7)); - - *addr = sl->sram_base; - *size = sizeof(loader_code_stm32f7); - - /* success */ - return 0; -} - -int stlink_flash_loader_run(stlink_t *sl, flash_loader_t *fl, - stm32_addr_t target, const uint8_t *buf, - size_t size) { - struct stlink_reg rr; - int i = 0; - size_t count = 0; - - // FIXME This can never return -1 - if (write_buffer_to_sram(sl, fl, buf, size) == -1) { - // IMPOSSIBLE! - printf("write_buffer_to_sram() == -1\n"); - return -1; - } - - count = size / sizeof(uint32_t); - if (size % sizeof(uint32_t)) ++count; - - /* setup core */ - stlink_write_reg(sl, fl->buf_addr, 0); /* source */ - stlink_write_reg(sl, target, 1); /* target */ - stlink_write_reg(sl, (uint32_t) count, 2); /* count */ - stlink_write_reg( - sl, 0, - 3); /* flash bank 0 (input), only used on F0, but armless fopr others */ - stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ - - /* run loader */ - stlink_run(sl); - - /* wait until done (reaches breakpoint) */ - for (i = 0; i < WAIT_ROUNDS; i++) { - usleep(10); - if (stlink_is_core_halted(sl)) break; - } - - if (i >= WAIT_ROUNDS) { - printf("flash loader run error\n"); - return -1; - } - - /* check written byte count */ - stlink_read_reg(sl, 2, &rr); - if (rr.r[2] != 0) { - printf("write error, count == %u\n", rr.r[2]); - return -1; - } - - return 0; -} diff --git a/src/common/platforms/stm32/flash_loader.h b/src/common/platforms/stm32/flash_loader.h deleted file mode 100644 index a3f072dfebd8640fd5382a1d89cb70a30edee70f..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/flash_loader.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * File: stlink.h - * - * This should contain all the common top level stlink interfaces, regardless - * of how the backend does the work.... - */ -#ifndef STLINK_FLASH_LOADER_H_ -#define STLINK_FLASH_LOADER_H_ - -#include <stdint.h> -#include <stddef.h> - -#include "stlink.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl); -int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t *addr, - size_t *size); -int stlink_flash_loader_run(stlink_t *sl, flash_loader_t *fl, - stm32_addr_t target, const uint8_t *buf, - size_t size); - -#ifdef __cplusplus -} -#endif - -#endif /* STLINK_FLASH_LOADER_H_ */ diff --git a/src/common/platforms/stm32/flasher.go b/src/common/platforms/stm32/flasher.go deleted file mode 100644 index 36cbad1149eb3e46e93db29d1f4ee7fd7597da95..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/flasher.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build linux - -package stm32 - -// #cgo CFLAGS: -I/usr/include/libusb-1.0/ -// #cgo LDFLAGS: -lusb-1.0 -// #include "stm32_flash.h" -import "C" - -import ( - "time" - "unsafe" - - "cesanta.com/common/go/fwbundle" - "github.com/cesanta/errors" -) - -type FlashOpts struct { - ShareName string - Timeout time.Duration -} - -func Flash(fw *fwbundle.FirmwareBundle, opts *FlashOpts) error { - data, err := fw.GetPartData("boot") - if err != nil { - return errors.Annotatef(err, "invalid manifest") - } - - flash_res := C.stm32_flash(C.CString(opts.ShareName), - unsafe.Pointer(&data[0]), - C.int(len(data))) - - if flash_res != 0 { - return errors.Errorf("flash failed") - } - - return nil -} diff --git a/src/common/platforms/stm32/stlink.h b/src/common/platforms/stm32/stlink.h deleted file mode 100644 index ac34dd067f2c8ae11d5f5caac274235e751b21d5..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/stlink.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * File: stlink.h - * - * This should contain all the common top level stlink interfaces, regardless - * of how the backend does the work.... - */ -#ifndef STLINK_H -#define STLINK_H - -#include <stdint.h> -#include <stddef.h> -#include <stdbool.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define STLINK_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - -// Max data transfer size. -// 6kB = max mem32_read block, 8kB sram -//#define Q_BUF_LEN 96 -#define Q_BUF_LEN (1024 * 100) - -// STLINK_DEBUG_RESETSYS, etc: -#define STLINK_CORE_RUNNING 0x80 -#define STLINK_CORE_HALTED 0x81 -#define STLINK_CORE_STAT_UNKNOWN -1 - -#define STLINK_GET_VERSION 0xf1 -#define STLINK_GET_CURRENT_MODE 0xf5 -#define STLINK_GET_TARGET_VOLTAGE 0xF7 - -#define STLINK_DEBUG_COMMAND 0xF2 -#define STLINK_DFU_COMMAND 0xF3 -#define STLINK_DFU_EXIT 0x07 - -// STLINK_GET_CURRENT_MODE -#define STLINK_DEV_DFU_MODE 0x00 -#define STLINK_DEV_MASS_MODE 0x01 -#define STLINK_DEV_DEBUG_MODE 0x02 -#define STLINK_DEV_UNKNOWN_MODE -1 - -// TODO - possible poor names... -#define STLINK_SWD_ENTER 0x30 -#define STLINK_SWD_READCOREID 0x32 // TBD -#define STLINK_JTAG_WRITEDEBUG_32BIT 0x35 -#define STLINK_JTAG_READDEBUG_32BIT 0x36 -#define STLINK_JTAG_DRIVE_NRST 0x3c - -#define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43 - -/* cortex core ids */ -// TODO clean this up... -#define STM32VL_CORE_ID 0x1ba01477 -#define STM32F7_CORE_ID 0x5ba02477 - -// Constant STM32 memory map figures -#define STM32_FLASH_BASE 0x08000000 -#define STM32_SRAM_BASE 0x20000000 - -// Baud rate divisors for SWDCLK -#define STLINK_SWDCLK_4MHZ_DIVISOR 0 -#define STLINK_SWDCLK_1P8MHZ_DIVISOR 1 -#define STLINK_SWDCLK_1P2MHZ_DIVISOR 2 -#define STLINK_SWDCLK_950KHZ_DIVISOR 3 -#define STLINK_SWDCLK_480KHZ_DIVISOR 7 -#define STLINK_SWDCLK_240KHZ_DIVISOR 15 -#define STLINK_SWDCLK_125KHZ_DIVISOR 31 -#define STLINK_SWDCLK_100KHZ_DIVISOR 40 -#define STLINK_SWDCLK_50KHZ_DIVISOR 79 -#define STLINK_SWDCLK_25KHZ_DIVISOR 158 -#define STLINK_SWDCLK_15KHZ_DIVISOR 265 -#define STLINK_SWDCLK_5KHZ_DIVISOR 798 - -#define STLINK_CHIPID_STM32_F7 0x449 - -/* Enough space to hold both a V2 command or a V1 command packaged as generic - * scsi*/ -#define C_BUF_LEN 32 - -struct stlink_reg { - uint32_t r[16]; - uint32_t s[32]; - uint32_t xpsr; - uint32_t main_sp; - uint32_t process_sp; - uint32_t rw; - uint32_t rw2; - uint8_t control; - uint8_t faultmask; - uint8_t basepri; - uint8_t primask; - uint32_t fpscr; -}; - -typedef uint32_t stm32_addr_t; - -typedef struct flash_loader { - stm32_addr_t loader_addr; /* loader sram adddr */ - stm32_addr_t buf_addr; /* buffer sram address */ -} flash_loader_t; - -typedef struct stlink_version_ { - uint32_t stlink_v; - uint32_t jtag_v; - uint32_t swim_v; - uint32_t st_vid; - uint32_t stlink_pid; -} stlink_version_t; - -typedef struct _stlink stlink_t; - -struct _stlink { - void *backend_data; - - // Room for the command header - unsigned char c_buf[C_BUF_LEN]; - // Data transferred from or to device - unsigned char q_buf[Q_BUF_LEN]; - int q_len; - - // transport layer verboseness: 0 for no debug info, 10 for lots - uint32_t core_id; - uint32_t chip_id; - int core_stat; - - char serial[16]; - int serial_size; - - stm32_addr_t flash_base; - size_t flash_size; - size_t flash_pgsz; - - /* sram settings */ - stm32_addr_t sram_base; - size_t sram_size; - - // bootloader - stm32_addr_t sys_base; - size_t sys_size; - - struct stlink_version_ version; -}; - -int stlink_enter_swd_mode(stlink_t *sl); -int stlink_enter_jtag_mode(stlink_t *sl); -int stlink_exit_debug_mode(stlink_t *sl); -int stlink_exit_dfu_mode(stlink_t *sl); -void stlink_close(stlink_t *sl); -int stlink_core_id(stlink_t *sl); -int stlink_reset(stlink_t *sl); -int stlink_jtag_reset(stlink_t *sl, int value); -int stlink_run(stlink_t *sl); -int stlink_status(stlink_t *sl); -int stlink_version(stlink_t *sl); -int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data); -int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len); -int stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data); -int stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len); -int stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len); -int stlink_read_all_regs(stlink_t *sl, struct stlink_reg *regp); -int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp); -int stlink_write_reg(stlink_t *sl, uint32_t reg, int idx); -int stlink_step(stlink_t *sl); -int stlink_current_mode(stlink_t *sl); -int stlink_force_debug(stlink_t *sl); -int stlink_target_voltage(stlink_t *sl); -int stlink_set_swdclk(stlink_t *sl, uint16_t divisor); -int stlink_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, - uint32_t length, uint8_t eraseonly); -int stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr); -int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, - uint32_t length); -int stlink_chip_id(stlink_t *sl, uint32_t *chip_id); -int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr); -uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr); -uint16_t read_uint16(const unsigned char *c, const int pt); -void stlink_core_stat(stlink_t *sl); -unsigned int is_bigendian(void); -uint32_t read_uint32(const unsigned char *c, const int pt); -void write_uint32(unsigned char *buf, uint32_t ui); -void write_uint16(unsigned char *buf, uint16_t ui); -bool stlink_is_core_halted(stlink_t *sl); -int write_buffer_to_sram(stlink_t *sl, flash_loader_t *fl, const uint8_t *buf, - size_t size); -int write_loader_to_sram(stlink_t *sl, stm32_addr_t *addr, size_t *size); -int stlink_load_device_params(stlink_t *sl); -void stlink_fwrite_finalize(stlink_t *sl, stm32_addr_t addr); - -#include "usb.h" -#include "flash_loader.h" - -#ifdef __cplusplus -} -#endif - -#endif /* STLINK_H */ diff --git a/src/common/platforms/stm32/stm32_flash.h b/src/common/platforms/stm32/stm32_flash.h deleted file mode 100644 index 2846ab712eb70edc3634e92706627f1e5e869587..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/stm32_flash.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef STM32_FLASH_H_ -#define STM32_FLASH_H_ - -int stm32_flash(const char *device_name, void *data, int len); - -#endif diff --git a/src/common/platforms/stm32/usb.c b/src/common/platforms/stm32/usb.c deleted file mode 100644 index a60e99f8bb4d1575838e72361f863f078ca66419..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/usb.c +++ /dev/null @@ -1,773 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <sys/time.h> -#include <sys/types.h> -#include <libusb.h> -#include <errno.h> -#include <unistd.h> - -#include "stlink.h" - -enum SCSI_Generic_Direction { SG_DXFER_TO_DEV = 0, SG_DXFER_FROM_DEV = 0x80 }; - -enum stlink_debug_commands { - STLINK_DEBUG_ENTER_JTAG = 0x00, - STLINK_DEBUG_GETSTATUS = 0x01, - STLINK_DEBUG_FORCEDEBUG = 0x02, - STLINK_DEBUG_RESETSYS = 0x03, - STLINK_DEBUG_READALLREGS = 0x04, - STLINK_DEBUG_READREG = 0x05, - STLINK_DEBUG_WRITEREG = 0x06, - STLINK_DEBUG_READMEM_32BIT = 0x07, - STLINK_DEBUG_WRITEMEM_32BIT = 0x08, - STLINK_DEBUG_RUNCORE = 0x09, - STLINK_DEBUG_STEPCORE = 0x0a, - STLINK_DEBUG_SETFP = 0x0b, - STLINK_DEBUG_WRITEMEM_8BIT = 0x0d, - STLINK_DEBUG_CLEARFP = 0x0e, - STLINK_DEBUG_WRITEDEBUGREG = 0x0f, - STLINK_DEBUG_ENTER = 0x20, - STLINK_DEBUG_EXIT = 0x21, - STLINK_DEBUG_READCOREID = 0x22, - STLINK_DEBUG_ENTER_SWD = 0xa3 -}; - -void _stlink_usb_close(stlink_t *sl) { - if (!sl) return; - - struct stlink_libusb *const handle = sl->backend_data; - // maybe we couldn't even get the usb device? - if (handle != NULL) { - if (handle->usb_handle != NULL) { - libusb_close(handle->usb_handle); - } - - libusb_exit(handle->libusb_ctx); - free(handle); - } -} - -ssize_t send_recv(struct stlink_libusb *handle, int terminate, - unsigned char *txbuf, size_t txsize, unsigned char *rxbuf, - size_t rxsize) { - /* note: txbuf and rxbuf can point to the same area */ - int res = 0; - int t; - - t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, txbuf, - (int) txsize, &res, 3000); - if (t) { - printf("[!] send_recv send request failed: %s\n", libusb_error_name(t)); - return -1; - } else if ((size_t) res != txsize) { - printf("[!] send_recv send request wrote %u bytes (instead of %u).\n", - (unsigned int) res, (unsigned int) txsize); - } - - if (rxsize != 0) { - t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, rxbuf, - (int) rxsize, &res, 3000); - if (t) { - printf("[!] send_recv read reply failed: %s\n", libusb_error_name(t)); - return -1; - } - } - - if ((handle->protocoll == 1) && terminate) { - /* Read the SG reply */ - unsigned char sg_buf[13]; - t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, sg_buf, 13, - &res, 3000); - if (t) { - printf("[!] send_recv read storage failed: %s\n", libusb_error_name(t)); - return -1; - } - /* The STLink doesn't seem to evaluate the sequence number */ - handle->sg_transfer_idx++; - } - - return res; -} - -static inline int send_only(struct stlink_libusb *handle, int terminate, - unsigned char *txbuf, size_t txsize) { - return (int) send_recv(handle, terminate, txbuf, txsize, NULL, 0); -} - -static int fill_command(stlink_t *sl, enum SCSI_Generic_Direction dir, - uint32_t len) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const cmd = sl->c_buf; - int i = 0; - memset(cmd, 0, sizeof(sl->c_buf)); - if (slu->protocoll == 1) { - cmd[i++] = 'U'; - cmd[i++] = 'S'; - cmd[i++] = 'B'; - cmd[i++] = 'C'; - write_uint32(&cmd[i], slu->sg_transfer_idx); - write_uint32(&cmd[i + 4], len); - i += 8; - cmd[i++] = (dir == SG_DXFER_FROM_DEV) ? 0x80 : 0; - cmd[i++] = 0; /* Logical unit */ - cmd[i++] = 0xa; /* Command length */ - } - return i; -} - -int _stlink_usb_version(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - uint32_t rep_len = 6; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_GET_VERSION; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_GET_VERSION\n"); - return (int) size; - } - - return 0; -} - -int32_t _stlink_usb_target_voltage(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const rdata = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - uint32_t rep_len = 8; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - uint32_t factor, reading; - int voltage; - - cmd[i++] = STLINK_GET_TARGET_VOLTAGE; - - size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_GET_TARGET_VOLTAGE\n"); - return -1; - } else if (size != 8) { - printf("[!] wrong length STLINK_GET_TARGET_VOLTAGE\n"); - return -1; - } - - factor = - (rdata[3] << 24) | (rdata[2] << 16) | (rdata[1] << 8) | (rdata[0] << 0); - reading = - (rdata[7] << 24) | (rdata[6] << 16) | (rdata[5] << 8) | (rdata[4] << 0); - voltage = 2400 * reading / factor; - - return voltage; -} - -int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const rdata = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - const int rep_len = 8; - - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_JTAG_READDEBUG_32BIT; - write_uint32(&cmd[i], addr); - size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_JTAG_READDEBUG_32BIT\n"); - return (int) size; - } - *data = read_uint32(rdata, 4); - return 0; -} - -int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const rdata = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - const int rep_len = 2; - - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_JTAG_WRITEDEBUG_32BIT; - write_uint32(&cmd[i], addr); - write_uint32(&cmd[i + 4], data); - size = send_recv(slu, 1, cmd, slu->cmd_len, rdata, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_JTAG_WRITEDEBUG_32BIT\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - int i, ret; - - i = fill_command(sl, SG_DXFER_TO_DEV, len); - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_WRITEMEM_32BIT; - write_uint32(&cmd[i], addr); - write_uint16(&cmd[i + 4], len); - ret = send_only(slu, 0, cmd, slu->cmd_len); - if (ret == -1) return ret; - - ret = send_only(slu, 1, data, len); - if (ret == -1) return ret; - - return 0; -} - -int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - int i, ret; - - i = fill_command(sl, SG_DXFER_TO_DEV, 0); - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_WRITEMEM_8BIT; - write_uint32(&cmd[i], addr); - write_uint16(&cmd[i + 4], len); - ret = send_only(slu, 0, cmd, slu->cmd_len); - if (ret == -1) return ret; - - ret = send_only(slu, 1, data, len); - if (ret == -1) return ret; - - return 0; -} - -int _stlink_usb_current_mode(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const cmd = sl->c_buf; - unsigned char *const data = sl->q_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_GET_CURRENT_MODE; - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_GET_CURRENT_MODE\n"); - return -1; - } - return sl->q_buf[0]; -} - -int _stlink_usb_core_id(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const cmd = sl->c_buf; - unsigned char *const data = sl->q_buf; - ssize_t size; - int rep_len = 4; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_READCOREID; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_READCOREID\n"); - return -1; - } - - sl->core_id = read_uint32(data, 0); - return 0; -} - -int _stlink_usb_status(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_GETSTATUS; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_GETSTATUS\n"); - return (int) size; - } - sl->q_len = (int) size; - - return 0; -} - -int _stlink_usb_force_debug(stlink_t *sl) { - struct stlink_libusb *slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_FORCEDEBUG; - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_FORCEDEBUG\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_enter_swd_mode(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - const int rep_len = 0; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_ENTER; - cmd[i++] = STLINK_DEBUG_ENTER_SWD; - - size = send_only(slu, 1, cmd, slu->cmd_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_ENTER\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_exit_dfu_mode(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int i = fill_command(sl, SG_DXFER_FROM_DEV, 0); - - cmd[i++] = STLINK_DFU_COMMAND; - cmd[i++] = STLINK_DFU_EXIT; - - size = send_only(slu, 1, cmd, slu->cmd_len); - if (size == -1) { - printf("[!] send_recv STLINK_DFU_EXIT\n"); - return (int) size; - } - - return 0; -} - -/** - * TODO - not convinced this does anything... - * @param sl - */ -int _stlink_usb_reset(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_RESETSYS; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_RESETSYS\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_jtag_reset(stlink_t *sl, int value) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_JTAG_DRIVE_NRST; - cmd[i++] = value; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_JTAG_DRIVE_NRST\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_step(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_STEPCORE; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_STEPCORE\n"); - return (int) size; - } - - return 0; -} - -/** - * This seems to do a good job of restarting things from the beginning? - * @param sl - */ -int _stlink_usb_run(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_RUNCORE; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_RUNCORE\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_set_swdclk(stlink_t *sl, uint16_t clk_divisor) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int rep_len = 2; - int i; - - // clock speed only supported by stlink/v2 and for firmware >= 22 - if (sl->version.stlink_v >= 2 && sl->version.jtag_v >= 22) { - i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_APIV2_SWD_SET_FREQ; - cmd[i++] = clk_divisor & 0xFF; - cmd[i++] = (clk_divisor >> 8) & 0xFF; - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_APIV2_SWD_SET_FREQ\n"); - return (int) size; - } - - return 0; - } else { - return -1; - } -} - -int _stlink_usb_exit_debug_mode(stlink_t *sl) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int i = fill_command(sl, SG_DXFER_FROM_DEV, 0); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_EXIT; - - size = send_only(slu, 1, cmd, slu->cmd_len); - if (size == -1) { - printf("[!] send_only STLINK_DEBUG_EXIT\n"); - return (int) size; - } - - return 0; -} - -int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - int i = fill_command(sl, SG_DXFER_FROM_DEV, len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_READMEM_32BIT; - write_uint32(&cmd[i], addr); - write_uint16(&cmd[i + 4], len); - - size = send_recv(slu, 1, cmd, slu->cmd_len, data, len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_READMEM_32BIT\n"); - return (int) size; - } - - sl->q_len = (int) size; - - return 0; -} - -int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - uint32_t r; - uint32_t rep_len = 4; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_READREG; - cmd[i++] = (uint8_t) r_idx; - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_READREG\n"); - return (int) size; - } - sl->q_len = (int) size; - r = read_uint32(sl->q_buf, 0); - - switch (r_idx) { - case 16: - regp->xpsr = r; - break; - case 17: - regp->main_sp = r; - break; - case 18: - regp->process_sp = r; - break; - case 19: - regp->rw = r; /* XXX ?(primask, basemask etc.) */ - break; - case 20: - regp->rw2 = r; /* XXX ?(primask, basemask etc.) */ - break; - default: - regp->r[r_idx] = r; - } - - return 0; -} - -int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) { - struct stlink_libusb *const slu = sl->backend_data; - unsigned char *const data = sl->q_buf; - unsigned char *const cmd = sl->c_buf; - ssize_t size; - uint32_t rep_len = 2; - int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); - - cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_WRITEREG; - cmd[i++] = idx; - write_uint32(&cmd[i], reg); - size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); - if (size == -1) { - printf("[!] send_recv STLINK_DEBUG_WRITEREG\n"); - return (int) size; - } - sl->q_len = (int) size; - - return 0; -} - -stlink_t *stlink_open_usb(bool reset, char serial[16]) { - stlink_t *sl = NULL; - struct stlink_libusb *slu = NULL; - int ret = -1; - int config; - - sl = calloc(1, sizeof(stlink_t)); - slu = calloc(1, sizeof(struct stlink_libusb)); - if (sl == NULL) goto on_malloc_error; - if (slu == NULL) goto on_malloc_error; - - sl->backend_data = slu; - - sl->core_stat = STLINK_CORE_STAT_UNKNOWN; - if (libusb_init(&(slu->libusb_ctx))) { - printf("failed to init libusb context, wrong version of libraries?\n"); - goto on_error; - } - - libusb_device **list; - /** @todo We should use ssize_t and use it as a counter if > 0. As per libusb - * API: ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device - * ***list) */ - int cnt = (int) libusb_get_device_list(slu->libusb_ctx, &list); - struct libusb_device_descriptor desc; - int devBus = 0; - int devAddr = 0; - - /* @TODO: Reading a environment variable in a usb open function is not very - nice, this - should be refactored and moved into the CLI tools, and instead of giving - USB_BUS:USB_ADDR a real stlink - serial string should be passed to this function. Probably people are using - this but this is very odd because - as programmer can change to multiple busses and it is better to detect them - based on serial. */ - char *device = getenv("STLINK_DEVICE"); - if (device) { - char *c = strchr(device, ':'); - if (c == NULL) { - printf("STLINK_DEVICE must be <USB_BUS>:<USB_ADDR> format\n"); - goto on_error; - } - devBus = atoi(device); - *c++ = 0; - devAddr = atoi(c); - printf("bus %03d dev %03d\n", devBus, devAddr); - } - - while (cnt--) { - libusb_get_device_descriptor(list[cnt], &desc); - if (desc.idVendor != STLINK_USB_VID_ST) continue; - - if (devBus && devAddr) { - if ((libusb_get_bus_number(list[cnt]) != devBus) || - (libusb_get_device_address(list[cnt]) != devAddr)) { - continue; - } - } - - if ((desc.idProduct == STLINK_USB_PID_STLINK_32L) || - (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO)) { - struct libusb_device_handle *handle; - - ret = libusb_open(list[cnt], &handle); - if (ret) continue; - - sl->serial_size = libusb_get_string_descriptor_ascii( - handle, desc.iSerialNumber, (unsigned char *) sl->serial, - sizeof(sl->serial)); - libusb_close(handle); - - if ((serial == NULL) || (*serial == 0)) break; - - if (sl->serial_size < 0) continue; - - if (memcmp(serial, &sl->serial, sl->serial_size) == 0) break; - - continue; - } - - if (desc.idProduct == STLINK_USB_PID_STLINK) { - slu->protocoll = 1; - break; - } - } - - if (cnt < 0) { - printf("Couldn't find %s ST-Link/V2 devices\n", - (devBus && devAddr) ? "matched" : "any"); - goto on_error; - } else { - ret = libusb_open(list[cnt], &slu->usb_handle); - if (ret != 0) { - printf("Error %d (%s) opening ST-Link/V2 device %03d:%03d\n", ret, - strerror(errno), libusb_get_bus_number(list[cnt]), - libusb_get_device_address(list[cnt])); - goto on_error; - } - } - - libusb_free_device_list(list, 1); - - if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) { - ret = libusb_detach_kernel_driver(slu->usb_handle, 0); - if (ret < 0) { - printf("libusb_detach_kernel_driver(() error %s\n", strerror(-ret)); - goto on_libusb_error; - } - } - - if (libusb_get_configuration(slu->usb_handle, &config)) { - /* this may fail for a previous configured device */ - printf("libusb_get_configuration()\n"); - goto on_libusb_error; - } - - if (config != 1) { - printf("setting new configuration (%d -> 1)\n", config); - if (libusb_set_configuration(slu->usb_handle, 1)) { - /* this may fail for a previous configured device */ - printf("libusb_set_configuration() failed\n"); - goto on_libusb_error; - } - } - - if (libusb_claim_interface(slu->usb_handle, 0)) { - printf( - "Stlink usb device found, but unable to claim (probably already in " - "use?)\n"); - goto on_libusb_error; - } - - // TODO - could use the scanning techniq from stm8 code here... - slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN; - if (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO) { - slu->ep_req = 1 /* ep req */ | LIBUSB_ENDPOINT_OUT; - } else { - slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT; - } - - slu->sg_transfer_idx = 0; - // TODO - never used at the moment, always CMD_SIZE - slu->cmd_len = (slu->protocoll == 1) ? STLINK_SG_SIZE : STLINK_CMD_SIZE; - - if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { - printf("-- exit_dfu_mode\n"); - stlink_exit_dfu_mode(sl); - } - - if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { - stlink_enter_swd_mode(sl); - } - - sl->version.stlink_v = 2; - - if (reset) { - if (sl->version.stlink_v > 1) stlink_jtag_reset(sl, 2); - stlink_reset(sl); - usleep(10000); - } - - ret = stlink_load_device_params(sl); - - // Set the stlink clock speed (default is 1800kHz) - stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); - -on_libusb_error: - if (ret == -1) { - stlink_close(sl); - return NULL; - } - - return sl; - -on_error: - if (slu->libusb_ctx) libusb_exit(slu->libusb_ctx); - -on_malloc_error: - if (sl != NULL) free(sl); - if (slu != NULL) free(slu); - - return NULL; -} diff --git a/src/common/platforms/stm32/usb.h b/src/common/platforms/stm32/usb.h deleted file mode 100644 index 6ee4ff3b41dda11ed14ab6d847c037ebccd19f94..0000000000000000000000000000000000000000 --- a/src/common/platforms/stm32/usb.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * File: stlink/usb.h - * Author: karl - * - * Created on October 1, 2011, 11:29 PM - */ - -#ifndef STLINK_USB_H -#define STLINK_USB_H - -#include <stdbool.h> -#include <libusb.h> - -#include "stlink.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define STLINK_USB_VID_ST 0x0483 -#define STLINK_USB_PID_STLINK 0x3744 -#define STLINK_USB_PID_STLINK_32L 0x3748 -#define STLINK_USB_PID_STLINK_NUCLEO 0x374b - -#define STLINK_SG_SIZE 31 -#define STLINK_CMD_SIZE 16 - -struct stlink_libusb { - libusb_context *libusb_ctx; - libusb_device_handle *usb_handle; - unsigned int ep_req; - unsigned int ep_rep; - int protocoll; - unsigned int sg_transfer_idx; - unsigned int cmd_len; -}; - -/** - * Open a stlink - * @param verbose Verbosity loglevel - * @param reset Reset stlink programmer - * @param serial Serial number to search for, when NULL the first stlink found - * is opened (binary format) - * @retval NULL Error while opening the stlink - * @retval !NULL Stlink found and ready to use - */ -stlink_t *stlink_open_usb(bool reset, char serial[16]); - -void _stlink_usb_close(stlink_t *sl); -int _stlink_usb_version(stlink_t *sl); -int32_t _stlink_usb_target_voltage(stlink_t *sl); -int _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data); -int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data); -int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len); -int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len); -int _stlink_usb_current_mode(stlink_t *sl); -int _stlink_usb_core_id(stlink_t *sl); -int _stlink_usb_status(stlink_t *sl); -int _stlink_usb_force_debug(stlink_t *sl); -int _stlink_usb_enter_swd_mode(stlink_t *sl); -int _stlink_usb_exit_dfu_mode(stlink_t *sl); -int _stlink_usb_reset(stlink_t *sl); -int _stlink_usb_jtag_reset(stlink_t *sl, int value); -int _stlink_usb_step(stlink_t *sl); -int _stlink_usb_run(stlink_t *sl); -int _stlink_usb_set_swdclk(stlink_t *sl, uint16_t clk_divisor); -int _stlink_usb_exit_debug_mode(stlink_t *sl); -int _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len); -int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp); -int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx); - -#ifdef __cplusplus -} -#endif - -#endif /* STLINK_USB_H */ diff --git a/src/mg_http.c b/src/mg_http.c index 5cd6f623a62cb15eeb08a656cdd115152aca40be..ef546c3732fd193ba671ddbf5caa9d0fb0e7981c 100644 --- a/src/mg_http.c +++ b/src/mg_http.c @@ -177,20 +177,29 @@ struct mg_http_proto_data { size_t rcvd; /* How many bytes we have received. */ }; -static void mg_http_conn_destructor(void *proto_data); +static void mg_http_proto_data_destructor(void *proto_data); + struct mg_connection *mg_connect_http_base( struct mg_mgr *mgr, MG_CB(mg_event_handler_t ev_handler, void *user_data), struct mg_connect_opts opts, const char *scheme1, const char *scheme2, const char *scheme_ssl1, const char *scheme_ssl2, const char *url, struct mg_str *path, struct mg_str *user_info, struct mg_str *host); -static struct mg_http_proto_data *mg_http_get_proto_data( +MG_INTERNAL struct mg_http_proto_data *mg_http_create_proto_data( struct mg_connection *c) { - if (c->proto_data == NULL) { - c->proto_data = MG_CALLOC(1, sizeof(struct mg_http_proto_data)); - c->proto_data_destructor = mg_http_conn_destructor; - } + /* If we have proto data from previous connection, flush it. */ + if (c->proto_data != NULL) { + void *pd = c->proto_data; + c->proto_data = NULL; + mg_http_proto_data_destructor(pd); + } + c->proto_data = MG_CALLOC(1, sizeof(struct mg_http_proto_data)); + c->proto_data_destructor = mg_http_proto_data_destructor; + return (struct mg_http_proto_data *) c->proto_data; +} +static struct mg_http_proto_data *mg_http_get_proto_data( + struct mg_connection *c) { return (struct mg_http_proto_data *) c->proto_data; } @@ -246,7 +255,7 @@ static void mg_http_free_reverse_proxy_data(struct mg_reverse_proxy_data *rpd) { } } -static void mg_http_conn_destructor(void *proto_data) { +static void mg_http_proto_data_destructor(void *proto_data) { struct mg_http_proto_data *pd = (struct mg_http_proto_data *) proto_data; #if MG_ENABLE_FILESYSTEM mg_http_free_proto_data_file(&pd->file); @@ -519,7 +528,8 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) { /* Rate-limited */ } if (pd->file.sent >= pd->file.cl) { - LOG(LL_DEBUG, ("%p done, %d bytes", nc, (int) pd->file.sent)); + LOG(LL_DEBUG, ("%p done, %d bytes, ka %d", nc, (int) pd->file.sent, + pd->file.keepalive)); if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE; mg_http_free_proto_data_file(&pd->file); } @@ -655,12 +665,12 @@ struct mg_http_endpoint *mg_http_get_endpoint_handler(struct mg_connection *nc, int matched, matched_max = 0; struct mg_http_endpoint *ep; - if (nc == NULL) { - return NULL; - } + if (nc == NULL) return NULL; pd = mg_http_get_proto_data(nc); + if (pd == NULL) return NULL; + ep = pd->endpoints; while (ep != NULL) { if ((matched = mg_match_prefix_n(ep->uri_pattern, *uri_path)) > 0) { @@ -732,13 +742,13 @@ void mg_http_handler(struct mg_connection *nc, int ev, if (ev == MG_EV_CLOSE) { #if MG_ENABLE_HTTP_CGI /* Close associated CGI forwarder connection */ - if (pd->cgi.cgi_nc != NULL) { + if (pd != NULL && pd->cgi.cgi_nc != NULL) { pd->cgi.cgi_nc->user_data = NULL; pd->cgi.cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY; } #endif #if MG_ENABLE_HTTP_STREAMING_MULTIPART - if (pd->mp_stream.boundary != NULL) { + if (pd != NULL && pd->mp_stream.boundary != NULL) { /* * Multipart message is in progress, but connection is closed. * Finish part and request with an error flag. @@ -768,14 +778,14 @@ void mg_http_handler(struct mg_connection *nc, int ev, deliver_chunk(nc, hm, req_len); mg_http_call_endpoint_handler(nc, ev2, hm); } - pd->rcvd = 0; - if (pd->endpoint_handler != NULL && pd->endpoint_handler != nc->handler) { + if (pd != NULL && pd->endpoint_handler != NULL && + pd->endpoint_handler != nc->handler) { mg_call(nc, pd->endpoint_handler, nc->user_data, ev, NULL); } } #if MG_ENABLE_FILESYSTEM - if (pd->file.fp != NULL) { + if (pd != NULL && pd->file.fp != NULL) { mg_http_transfer_file_data(nc); } #endif @@ -783,7 +793,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, mg_call(nc, nc->handler, nc->user_data, ev, ev_data); #if MG_ENABLE_HTTP_STREAMING_MULTIPART - if (pd->mp_stream.boundary != NULL && + if (pd != NULL && pd->mp_stream.boundary != NULL && (ev == MG_EV_RECV || ev == MG_EV_POLL)) { if (ev == MG_EV_RECV) { pd->rcvd += *(int *) ev_data; @@ -798,11 +808,16 @@ void mg_http_handler(struct mg_connection *nc, int ev, if (ev == MG_EV_RECV) { struct mg_str *s; - pd->rcvd += *(int *) ev_data; again: req_len = mg_parse_http(io->buf, io->len, hm, is_req); + if (req_len > 0) { + /* New request - new proto data */ + pd = mg_http_create_proto_data(nc); + pd->rcvd = io->len; + } + if (req_len > 0 && (s = mg_get_http_header(hm, "Transfer-Encoding")) != NULL && mg_vcasecmp(s, "chunked") == 0) { @@ -914,18 +929,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, /* If this is a CGI request, we are not done either. */ if (pd->cgi.cgi_nc != NULL) request_done = 0; #endif - if (request_done) { - /* This request is done but we may receive another on this connection. - */ - mg_http_conn_destructor(pd); - nc->proto_data = NULL; - if (io->len > 0) { - /* We already have data for the next one, restart parsing. */ - pd = mg_http_get_proto_data(nc); - pd->rcvd = io->len; - goto again; - } - } + if (request_done && io->len > 0) goto again; } } } @@ -3065,6 +3069,7 @@ void mg_register_http_endpoint_opt(struct mg_connection *nc, if (new_ep == NULL) return; pd = mg_http_get_proto_data(nc); + if (pd == NULL) pd = mg_http_create_proto_data(nc); new_ep->uri_pattern = mg_strdup(mg_mk_str(uri_path)); if (opts.auth_domain != NULL && opts.auth_file != NULL) { new_ep->auth_domain = strdup(opts.auth_domain); diff --git a/src/mg_internal.h b/src/mg_internal.h index 0e62448e9d876579798f4db5b7e4129d9298a46f..250b6fe1000faf5910215d453fc7d715d28ddf33 100644 --- a/src/mg_internal.h +++ b/src/mg_internal.h @@ -84,6 +84,9 @@ extern void *(*test_calloc)(size_t count, size_t size); #if MG_ENABLE_HTTP struct mg_serve_http_opts; +MG_INTERNAL struct mg_http_proto_data *mg_http_create_proto_data( + struct mg_connection *c); + /* * Reassemble the content of the buffer (buf, blen) which should be * in the HTTP chunked encoding, by collapsing data chunks to the diff --git a/src/mg_modules.mk b/src/mg_modules.mk index b53c53b1bf1c263d671c38dbc48a2ae94e5ffe00..e0e51bc7a683cab7b9621f2c138b8f139ebc101e 100644 --- a/src/mg_modules.mk +++ b/src/mg_modules.mk @@ -19,6 +19,7 @@ HEADERS = mg_common.h \ $(COMMON)/platforms/platform_nxp_lpc.h \ $(COMMON)/platforms/platform_nxp_kinetis.h \ $(COMMON)/platforms/platform_pic32.h \ + $(COMMON)/platforms/platform_rs14100.h \ $(COMMON)/platforms/platform_stm32.h \ $(COMMON)/platforms/lwip/mg_lwip.h \ $(COMMON)/cs_md5.h \ diff --git a/src/mg_mqtt.c b/src/mg_mqtt.c index 68069e8d1c1ab4fc0ccddbc680ddb6c4d46f182b..9ab66bc632c2aa5c641a0e33239e7ae55ab85fcf 100644 --- a/src/mg_mqtt.c +++ b/src/mg_mqtt.c @@ -24,7 +24,7 @@ static const char *scanto(const char *p, struct mg_str *s) { MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { uint8_t header; size_t len = 0, len_len = 0; - const char *p, *end; + const char *p, *end, *eop = &io->buf[io->len]; unsigned char lc = 0; int cmd; @@ -35,7 +35,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { /* decode mqtt variable length */ len = len_len = 0; p = io->buf + 1; - while ((size_t)(p - io->buf) < io->len) { + while (p < eop) { lc = *((const unsigned char *) p++); len += (lc & 0x7f) << 7 * len_len; len_len++; @@ -44,9 +44,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { } end = p + len; - if (lc & 0x80 || len > (io->len - (p - io->buf))) { - return MG_MQTT_ERROR_INCOMPLETE_MSG; - } + if (lc & 0x80 || end > eop) return MG_MQTT_ERROR_INCOMPLETE_MSG; mm->cmd = cmd; mm->qos = MG_MQTT_GET_QOS(header); @@ -100,7 +98,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { case MG_MQTT_CMD_PUBREL: case MG_MQTT_CMD_PUBCOMP: case MG_MQTT_CMD_SUBACK: + if (end - p < 2) return MG_MQTT_ERROR_MALFORMED_MSG; mm->message_id = getu16(p); + p += 2; break; case MG_MQTT_CMD_PUBLISH: { p = scanto(p, &mm->topic); diff --git a/src/mg_net.c b/src/mg_net.c index 3b1b7038fccd8b46ef322ac6a542e388ba54010e..12c1b17c4a8738d2155c770e7c1d609908ca08e4 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -341,8 +341,8 @@ static int mg_resolve2(const char *host, struct in_addr *ina) { return 0; } for (p = servinfo; p != NULL; p = p->ai_next) { - memcpy(&h, &p->ai_addr, sizeof(struct sockaddr_in *)); - memcpy(ina, &h->sin_addr, sizeof(ina)); + memcpy(&h, &p->ai_addr, sizeof(h)); + memcpy(ina, &h->sin_addr, sizeof(*ina)); } freeaddrinfo(servinfo); return 1; @@ -877,6 +877,16 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address, return mg_connect_opt(mgr, address, MG_CB(callback, user_data), opts); } +void mg_ev_handler_empty(struct mg_connection *c, int ev, + void *ev_data MG_UD_ARG(void *user_data)) { + (void) c; + (void) ev; + (void) ev_data; +#if MG_ENABLE_CALLBACK_USERDATA + (void) user_data; +#endif +} + struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data), @@ -888,6 +898,8 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts); + if (callback == NULL) callback = mg_ev_handler_empty; + if ((nc = mg_create_connection(mgr, callback, add_sock_opts)) == NULL) { return NULL; } @@ -1001,10 +1013,7 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, opts.user_data = user_data; #endif - if (callback == NULL) { - MG_SET_PTRPTR(opts.error_string, "handler is required"); - return NULL; - } + if (callback == NULL) callback = mg_ev_handler_empty; MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts); diff --git a/src/mg_ssl_if_openssl.c b/src/mg_ssl_if_openssl.c index ef8342fc3c92e12ac59636e8f29a1cc3076bb770..98af8e29c8dc39f6f6a85edea4bdddcc8cc24acb 100644 --- a/src/mg_ssl_if_openssl.c +++ b/src/mg_ssl_if_openssl.c @@ -310,7 +310,7 @@ static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx, const char *cl) { : MG_SSL_ERROR); } -#ifndef KR_VERSION +#if !defined(KR_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) static unsigned int mg_ssl_if_ossl_psk_cb(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, @@ -376,10 +376,10 @@ static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(struct mg_ssl_if_ctx *ctx, (void) ctx; (void) identity; (void) key_str; - /* Krypton does not support PSK. */ + /* Krypton / LibreSSL does not support PSK. */ return MG_SSL_ERROR; } -#endif /* defined(KR_VERSION) */ +#endif /* !defined(KR_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) */ const char *mg_set_ssl(struct mg_connection *nc, const char *cert, const char *ca_cert) { diff --git a/test/Makefile b/test/Makefile index 97f41c9ae817ad08fe299d04d13b11a7f40c79e3..b3457bf928dc5e8d03ba1dc758254a2ab805b779 100644 --- a/test/Makefile +++ b/test/Makefile @@ -11,7 +11,7 @@ COMMON_DIR_DEV = ../../common # Our dev repo and public mongoose repo have different layouts, so here # we make it work on both -ifneq ("$(wildcard ../../fw)","") +ifneq ("$(wildcard ../../common.mk)","") COMMON_PARENT = ../.. else COMMON_PARENT = $(SRC_DIR) diff --git a/test/unit_test.c b/test/unit_test.c index 5901c21c36159c78bd83e13aa68ed51c069af2f1..5eb919cab761df7791938bb7ea952f0e8e60e7af 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -975,12 +975,6 @@ static void connect_fail_cb(struct mg_connection *nc, int ev, void *p) { } } -static void ev_handler_empty(struct mg_connection *nc, int ev, void *p) { - (void) nc; - (void) ev; - (void) p; -} - static const char *test_connection_errors(void) { struct mg_mgr mgr; struct mg_bind_opts bopts; @@ -995,25 +989,21 @@ static const char *test_connection_errors(void) { bopts.error_string = &error_string; ASSERT(mg_bind_opt(&mgr, "blah://12", NULL, bopts) == NULL); - ASSERT_STREQ(error_string, "handler is required"); - - ASSERT(mg_bind_opt(&mgr, "blah://12", ev_handler_empty, bopts) == NULL); ASSERT_STREQ(error_string, "cannot parse address"); - ASSERT(mg_bind_opt(&mgr, "tcp://8.8.8.8:88", ev_handler_empty, bopts) == - NULL); + ASSERT(mg_bind_opt(&mgr, "tcp://8.8.8.8:88", NULL, bopts) == NULL); ASSERT_STREQ(error_string, "failed to open listener"); #if MG_ENABLE_SSL bopts.ssl_cert = S_PEM; - ASSERT(mg_bind_opt(&mgr, "udp://:0", ev_handler_empty, bopts) == NULL); + ASSERT(mg_bind_opt(&mgr, "udp://:0", NULL, bopts) == NULL); ASSERT_STREQ(error_string, "SSL for UDP is not supported"); bopts.ssl_cert = "no_such_file"; - ASSERT(mg_bind_opt(&mgr, "tcp://:0", ev_handler_empty, bopts) == NULL); + ASSERT(mg_bind_opt(&mgr, "tcp://:0", NULL, bopts) == NULL); ASSERT_STREQ(error_string, "Invalid SSL cert"); bopts.ssl_cert = NULL; bopts.ssl_ca_cert = "no_such_file"; - ASSERT(mg_bind_opt(&mgr, "tcp://:0", ev_handler_empty, bopts) == NULL); + ASSERT(mg_bind_opt(&mgr, "tcp://:0", NULL, bopts) == NULL); ASSERT_STREQ(error_string, "Invalid SSL CA cert"); #endif @@ -1710,7 +1700,7 @@ static void cb10(struct mg_connection *nc, int ev, void *ev_data) { } } -static void endpoint_handler(struct mg_connection *nc, int ev, void *ev_data) { +static void default_handler(struct mg_connection *nc, int ev, void *ev_data) { struct http_message *hm = (struct http_message *) ev_data; (void) ev_data; @@ -1724,7 +1714,8 @@ static void endpoint_handler(struct mg_connection *nc, int ev, void *ev_data) { } } else if (ev == MG_EV_CLOSE) { if (nc->listener != NULL) { - (*(int *) nc->listener->user_data) += 100; + (*(int *) nc->listener->user_data) += 1; + DBG(("%p == default close", nc)); } } } @@ -1737,7 +1728,8 @@ static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) { nc->flags |= MG_F_SEND_AND_CLOSE; break; case MG_EV_CLOSE: - (*(int *) nc->listener->user_data)++; + DBG(("%p == hello1 close", nc)); + (*(int *) nc->listener->user_data) += 10; break; } } @@ -1750,7 +1742,8 @@ static void handle_hello2(struct mg_connection *nc, int ev, void *ev_data) { nc->flags |= MG_F_SEND_AND_CLOSE; break; case MG_EV_CLOSE: - (*(int *) nc->listener->user_data)++; + DBG(("%p == hello2 close", nc)); + (*(int *) nc->listener->user_data) += 100; break; } } @@ -1763,7 +1756,8 @@ static void handle_hello5(struct mg_connection *nc, int ev, void *ev_data) { nc->flags |= MG_F_SEND_AND_CLOSE; break; case MG_EV_CLOSE: - (*(int *) nc->listener->user_data)++; + DBG(("%p == hello5 close", nc)); + (*(int *) nc->listener->user_data) += 1000; break; } } @@ -1823,7 +1817,7 @@ static const char *test_http_endpoints(void) { mg_mgr_init(&mgr, NULL); /* mgr.hexdump_file = "-"; */ - ASSERT((nc = mg_bind(&mgr, local_addr, endpoint_handler)) != NULL); + ASSERT((nc = mg_bind(&mgr, local_addr, default_handler)) != NULL); mg_register_http_endpoint(nc, "/hello1", handle_hello1 MG_UD_ARG(NULL)); mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2 MG_UD_ARG(NULL)); @@ -1888,7 +1882,7 @@ static const char *test_http_endpoints(void) { poll_until(&mgr, 1, c_str_ne, buf, (void *) ""); ASSERT_STREQ(buf, "[I am Hello again] 37"); - ASSERT_EQ(close_count, 700); + ASSERT_EQ(close_count, 1117); mg_mgr_free(&mgr); @@ -1997,7 +1991,7 @@ static const char *test_http_serve_file_streaming(void) { ASSERT((nc = mg_connect(&mgr, local_addr, srv2)) != NULL); mg_set_protocol_http_websocket(nc); nc->user_data = &status; - mg_printf(nc, "GET / HTTP/1.1\r\n\r\n"); + mg_printf(nc, "GET / HTTP/1.0\r\n\r\n"); poll_until(&mgr, 30, c_int_ne, &status, (void *) 0); ASSERT_EQ(status, 1); mg_mgr_free(&mgr); @@ -4003,6 +3997,7 @@ static const char *test_http_chunk2(void) { nc.mgr = &mgr; nc.sock = INVALID_SOCKET; nc.handler = eh_chunk2; + mg_http_create_proto_data(&nc); hm.message.len = hm.body.len = ~0; s_handle_chunk_event = 0; @@ -4135,12 +4130,6 @@ static void cb_mp_send_one_byte(struct mg_connection *nc, int ev, void *p) { } } -static void cb_mp_empty(struct mg_connection *nc, int ev, void *p) { - (void) nc; - (void) ev; - (void) p; -} - static const char b1[] = "111111111111111111111111111111111111111111111111111111111111111\r\n" "111111111111111111111111111111111111111111111111111111111111111\r\n" @@ -4264,13 +4253,13 @@ static const char *test_http_multipart2(void) { "\r\n--Asrf456BGe4h\r\n", b1, b2, b4); /* Testing delivering to endpoint handler*/ - nc_listen = mg_bind(&mgr, "8766", cb_mp_empty); + nc_listen = mg_bind(&mgr, "8766", NULL); nc_listen->user_data = &mpd; mg_set_protocol_http_websocket(nc_listen); mg_register_http_endpoint(nc_listen, "/test", cb_mp_srv MG_UD_ARG(NULL)); - ASSERT((c = mg_connect_http(&mgr, cb_mp_empty, "http://127.0.0.1:8766/test", + ASSERT((c = mg_connect_http(&mgr, NULL, "http://127.0.0.1:8766/test", "Connection: keep-alive\r\nContent-Type: " "multipart/form-data; boundary=Asrf456BGe4h", multi_part_req)) != NULL); @@ -4307,7 +4296,7 @@ static const char *test_http_multipart2(void) { /* Test interrupted request */ multi_part_req[1800] = '\0'; c = mg_connect_http( - &mgr, cb_mp_empty, "http://127.0.0.1:8765", + &mgr, NULL, "http://127.0.0.1:8765", "Content-Type: multipart/form-data; boundary=Asrf456BGe4h", multi_part_req); @@ -4328,7 +4317,7 @@ static const char *test_http_multipart2(void) { ASSERT( mg_connect_http( - &mgr, cb_mp_empty, "http://127.0.0.1:8766/test", + &mgr, NULL, "http://127.0.0.1:8766/test", "Content-Type: multipart/form-data; boundary=Asrf456BGe4h", "\r\n--Asrf456BGe4h\r\n" "Content-Disposition: form-data; name=\"d\"; filename=\"small\"\r\n" @@ -4348,7 +4337,7 @@ static const char *test_http_multipart2(void) { * See https://github.com/cesanta/dev/issues/6974 * This request should not lead to crash */ - c = mg_connect(&mgr, "127.0.0.1:8766", cb_mp_empty); + c = mg_connect(&mgr, "127.0.0.1:8766", NULL); mg_printf(c, "POST /test HTTP/1.1\r\n" "Connection: keep-alive\r\n" @@ -4401,7 +4390,7 @@ static const char *test_http_multipart_pipeline(void) { snprintf(multi_part_req, sizeof(multi_part_req), multi_part_req_fmt, "\r\n--Asrf456BGe4h\r\n", b1, b2, b4); - ASSERT((c = mg_connect_http(&mgr, cb_mp_empty, "http://127.0.0.1:8765/test", + ASSERT((c = mg_connect_http(&mgr, NULL, "http://127.0.0.1:8765/test", "Content-Type: " "multipart/form-data;boundary=Asrf456BGe4h\r\n" "Connection: keep-alive", @@ -5685,7 +5674,7 @@ static const char *test_socks(void) { mg_set_protocol_http_websocket(c); /* Start socks proxy */ - ASSERT((c = mg_bind(&mgr, proxy_addr, ev_handler_empty)) != NULL); + ASSERT((c = mg_bind(&mgr, proxy_addr, NULL)) != NULL); mg_set_protocol_socks(c); /* Create HTTP client that uses socks proxy */