Skip to content

stm32: Add support for PYBD boards #4669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ec93e58
drivers/memory: Add mp_spiflash_deepsleep() function.
dpgeorge Apr 3, 2019
870f0a7
extmod/modlwip: Use mp_sched_schedule to schedule socket callback.
dpgeorge Apr 3, 2019
1f931f1
extmod/modlwip: Minor improvements to TCP send behaviour.
dpgeorge Apr 3, 2019
1fb1be0
lib/netutils: Add DHCP server component.
dpgeorge Apr 3, 2019
cfa4e3c
lib: Add new submodule for mbedtls, currently v2.16.0.
dpgeorge Apr 3, 2019
2dc84c9
stm32: Integrate mbedtls for ussl module.
dpgeorge Apr 3, 2019
6ce52f7
stm32/lwip_inc: Update lwIP config and enable mDNS.
dpgeorge Apr 3, 2019
93b2e83
stm32/qspi: Use MPU to prevent access to invalid SPI flash memory region
dpgeorge Apr 3, 2019
7921158
stm32: Enable lwIP mDNS responder.
dpgeorge Apr 3, 2019
8e36c86
stm32/modpyb: Add pyb.country() function to set the country.
dpgeorge Apr 3, 2019
4ae7832
stm32/extint: Add extint_set() function for internal C access to EXTI.
dpgeorge Apr 3, 2019
a83491d
stm32/mphalport: Add support for having MAC in OTP region.
dpgeorge Apr 3, 2019
523d56a
.gitattributes: Make *.a be binary files.
dpgeorge Apr 3, 2019
086e8c0
stm32: Add driver for CYW43xx WiFi chips.
dpgeorge Apr 3, 2019
d8e90f7
stm32: Add low-level SDIO interface for cyw43 driver.
dpgeorge Apr 3, 2019
ce85c97
stm32: Add network.WLAN class for cyw43 driver.
dpgeorge Apr 3, 2019
76eff13
stm32: Integrate in the cyw43 driver and network.WLAN class.
dpgeorge Apr 3, 2019
b5ab74e
stm32/mpconfigport.h: Enable modules useful for networking.
dpgeorge Apr 3, 2019
6100c95
stm32/powerctrl: Wake and sleep external QSPI flash in MCU stop mode.
dpgeorge Apr 3, 2019
f2a1c22
stm32/usb: Update USB interface to support msc and port keyword args.
dpgeorge Apr 3, 2019
87a9e99
stm32/modules: Add various modules useful for networking.
dpgeorge Apr 3, 2019
0cc6421
stm32/boards/make-pins.py: Allow a pin to only have a cpu name.
dpgeorge Apr 3, 2019
be49c0f
stm32/modmachine: Enable machine.RTC() class, so ntptime works.
dpgeorge Apr 3, 2019
4417c03
stm32/boards: Add board definition files for PYBD -SF2, -SF3, -SF6.
dpgeorge Apr 3, 2019
bae3179
stm32/boards: Remove USB_VBUS and USB_ID from PYBD pin list.
dpgeorge Apr 6, 2019
a209236
stm32/cyw43: For sta.config('essid') return SSID of network it's on.
dpgeorge Apr 8, 2019
7bc7a5a
stm32/cyw43: Add support for setting auth when connecting.
dpgeorge Apr 11, 2019
297acc9
stm32/network_cyw43: Update to pass through auth setting in connect.
dpgeorge Apr 11, 2019
87b2be9
stm32/boards/PYBD: Enable MICROPY_HW_RTC_USE_BYPASS.
dpgeorge Apr 11, 2019
caa425b
Merge branch 'master' into stm32-pybd
dpgeorge Apr 11, 2019
60b1acc
stm32/qspi: Abort any transfers if peripheral is busy.
dpgeorge Apr 11, 2019
1dcea07
stm32/powerctrl: Fix up ordering and config of QSPI deepsleep.
dpgeorge Apr 11, 2019
1e5bea3
stm32/cyw43: Update to improve connection at edge of cell.
dpgeorge Apr 11, 2019
e8f4a6b
Merge branch 'master' into stm32-pybd
dpgeorge Apr 12, 2019
3e3dd81
py/py.mk: Move mdns source from stm32 Makefile to global py.mk.
dpgeorge Apr 12, 2019
4c9b88e
lib/netutils/dhcpserver: Guard by MICROPY_PY_LWIP.
dpgeorge Apr 12, 2019
eeb6477
stm32/network_cyw43: Move CYW43 config guard above lwip includes.
dpgeorge Apr 12, 2019
4fdc731
stm32/powerctrl: Guard SPI flash calls with QSPI config macro.
dpgeorge Apr 12, 2019
d1444f5
Merge branch 'master' into stm32-pybd
dpgeorge Apr 18, 2019
5909369
stm32/cyw43: Update to fix async event handling during deinit.
dpgeorge Apr 25, 2019
2bf3c24
Merge branch 'master' into stm32-pybd
dpgeorge Apr 29, 2019
bf9bcc1
lib/netutils/dhcpserver: Add dhcp_server_deinit() function to free mem.
dpgeorge Apr 30, 2019
a13e586
stm32/cyw43: Free all lwIP memory when doing deinit() of WLAN.
dpgeorge Apr 30, 2019
a3d4ca6
Merge branch 'master' into stm32-pybd
dpgeorge May 22, 2019
533a2e1
stm32/factoryreset: Add pyb.country to initial boot.py file.
dpgeorge May 22, 2019
d28ef85
stm32/boards/PYBD_SF6: Add UART7 definition.
dpgeorge May 22, 2019
2b05d88
Merge branch 'master' into stm32-pybd
dpgeorge May 24, 2019
a9b1d3c
Merge branch 'master' into stm32-pybd
dpgeorge May 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*.bat text eol=crlf

# These are binary so should never be modified by git.
*.a binary
*.png binary
*.jpg binary
*.dxf binary
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@
[submodule "lib/nrfx"]
path = lib/nrfx
url = https://github.com/NordicSemiconductor/nrfx.git
[submodule "lib/mbedtls"]
path = lib/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
10 changes: 10 additions & 0 deletions drivers/memory/spiflash.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ void mp_spiflash_init(mp_spiflash_t *self) {

mp_spiflash_acquire_bus(self);

mp_spiflash_deepsleep(self, 0);

#if defined(CHECK_DEVID)
// Validate device id
uint32_t devid = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3);
Expand Down Expand Up @@ -482,3 +484,11 @@ int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, con
mp_spiflash_release_bus(self);
return 0;
}

void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) {
if (value) {
mp_spiflash_write_cmd(self, 0xb9); // sleep
} else {
mp_spiflash_write_cmd(self, 0xab); // wake
}
}
2 changes: 2 additions & 0 deletions drivers/memory/spiflash.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,6 @@ void mp_spiflash_cache_flush(mp_spiflash_t *self);
void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src);

void mp_spiflash_deepsleep(mp_spiflash_t *self, int value);

#endif // MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H
22 changes: 19 additions & 3 deletions extmod/modlwip.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ STATIC void lwip_socket_free_incoming(lwip_socket_obj_t *socket) {

static inline void exec_user_callback(lwip_socket_obj_t *socket) {
if (socket->callback != MP_OBJ_NULL) {
mp_call_function_1_protected(socket->callback, MP_OBJ_FROM_PTR(socket));
mp_sched_schedule(socket->callback, MP_OBJ_FROM_PTR(socket));
}
}

Expand Down Expand Up @@ -637,22 +637,29 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui

u16_t available = tcp_sndbuf(socket->pcb.tcp);

if (available == 0) {
if (available == 0 || tcp_sndqueuelen(socket->pcb.tcp) >= TCP_SND_QUEUELEN) {
// Non-blocking socket
if (socket->timeout == 0) {
MICROPY_PY_LWIP_EXIT
*_errno = MP_EAGAIN;
return MP_STREAM_ERROR;
}

err_t err = tcp_output(socket->pcb.tcp);
if (err != ERR_OK) {
MICROPY_PY_LWIP_EXIT
*_errno = error_lookup_table[-err];
return MP_STREAM_ERROR;
}

mp_uint_t start = mp_hal_ticks_ms();
// Assume that STATE_PEER_CLOSED may mean half-closed connection, where peer closed it
// sending direction, but not receiving. Consequently, check for both STATE_CONNECTED
// and STATE_PEER_CLOSED as normal conditions and still waiting for buffers to be sent.
// If peer fully closed socket, we would have socket->state set to ERR_RST (connection
// reset) by error callback.
// Avoid sending too small packets, so wait until at least 16 bytes available
while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) {
while (socket->state >= STATE_CONNECTED && ((available = tcp_sndbuf(socket->pcb.tcp)) < 16 || tcp_sndqueuelen(socket->pcb.tcp) >= TCP_SND_QUEUELEN)) {
MICROPY_PY_LWIP_EXIT
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = MP_ETIMEDOUT;
Expand All @@ -669,6 +676,15 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
u16_t write_len = MIN(available, len);

err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
if (err == ERR_MEM) {
for (int i = 0; i < 100 && err == ERR_MEM; ++i) {
err = tcp_output(socket->pcb.tcp);
MICROPY_PY_LWIP_EXIT
poll_sockets();
MICROPY_PY_LWIP_REENTER
err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
}
}

// If the output buffer is getting full then send the data to the lower layers
if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) {
Expand Down
1 change: 1 addition & 0 deletions lib/mbedtls
Submodule mbedtls added at fb1972
293 changes: 293 additions & 0 deletions lib/netutils/dhcpserver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018-2019 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

// For DHCP specs see:
// https://www.ietf.org/rfc/rfc2131.txt
// https://tools.ietf.org/html/rfc2132 -- DHCP Options and BOOTP Vendor Extensions

#include <stdio.h>
#include <string.h>
#include "py/mperrno.h"
#include "py/mphal.h"

#if MICROPY_PY_LWIP

#include "lib/netutils/dhcpserver.h"
#include "lwip/udp.h"

#define DHCPDISCOVER (1)
#define DHCPOFFER (2)
#define DHCPREQUEST (3)
#define DHCPDECLINE (4)
#define DHCPACK (5)
#define DHCPNACK (6)
#define DHCPRELEASE (7)
#define DHCPINFORM (8)

#define DHCP_OPT_PAD (0)
#define DHCP_OPT_SUBNET_MASK (1)
#define DHCP_OPT_ROUTER (3)
#define DHCP_OPT_DNS (6)
#define DHCP_OPT_HOST_NAME (12)
#define DHCP_OPT_REQUESTED_IP (50)
#define DHCP_OPT_IP_LEASE_TIME (51)
#define DHCP_OPT_MSG_TYPE (53)
#define DHCP_OPT_SERVER_ID (54)
#define DHCP_OPT_PARAM_REQUEST_LIST (55)
#define DHCP_OPT_MAX_MSG_SIZE (57)
#define DHCP_OPT_VENDOR_CLASS_ID (60)
#define DHCP_OPT_CLIENT_ID (61)
#define DHCP_OPT_END (255)

#define PORT_DHCP_SERVER (67)
#define PORT_DHCP_CLIENT (68)

#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8)
#define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds

#define MAC_LEN (6)
#define MAKE_IP4(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))

typedef struct {
uint8_t op; // message opcode
uint8_t htype; // hardware address type
uint8_t hlen; // hardware address length
uint8_t hops;
uint32_t xid; // transaction id, chosen by client
uint16_t secs; // client seconds elapsed
uint16_t flags;
uint8_t ciaddr[4]; // client IP address
uint8_t yiaddr[4]; // your IP address
uint8_t siaddr[4]; // next server IP address
uint8_t giaddr[4]; // relay agent IP address
uint8_t chaddr[16]; // client hardware address
uint8_t sname[64]; // server host name
uint8_t file[128]; // boot file name
uint8_t options[312]; // optional parameters, variable, starts with magic
} dhcp_msg_t;

static int dhcp_socket_new_dgram(struct udp_pcb **udp, void *cb_data, udp_recv_fn cb_udp_recv) {
// family is AF_INET
// type is SOCK_DGRAM

*udp = udp_new();
if (*udp == NULL) {
return -MP_ENOMEM;
}

// Register callback
udp_recv(*udp, cb_udp_recv, (void*)cb_data);

return 0; // success
}

static int dhcp_socket_bind(struct udp_pcb **udp, uint32_t ip, uint16_t port) {
ip_addr_t addr;
IP4_ADDR(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff);
// TODO convert lwIP errors to errno
return udp_bind(*udp, &addr, port);
}

static int dhcp_socket_sendto(struct udp_pcb **udp, const void *buf, size_t len, uint32_t ip, uint16_t port) {
if (len > 0xffff) {
len = 0xffff;
}

struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (p == NULL) {
return -MP_ENOMEM;
}

memcpy(p->payload, buf, len);

ip_addr_t dest;
IP4_ADDR(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff);
err_t err = udp_sendto(*udp, p, &dest, port);

pbuf_free(p);

if (err != ERR_OK) {
return err;
}

return len;
}

static uint8_t *opt_find(uint8_t *opt, uint8_t cmd) {
for (int i = 0; i < 308 && opt[i] != DHCP_OPT_END;) {
if (opt[i] == cmd) {
return &opt[i];
}
i += 2 + opt[i + 1];
}
return NULL;
}

static void opt_write_n(uint8_t **opt, uint8_t cmd, size_t n, void *data) {
uint8_t *o = *opt;
*o++ = cmd;
*o++ = n;
memcpy(o, data, n);
*opt = o + n;
}

static void opt_write_u8(uint8_t **opt, uint8_t cmd, uint8_t val) {
uint8_t *o = *opt;
*o++ = cmd;
*o++ = 1;
*o++ = val;
*opt = o;
}

static void opt_write_u32(uint8_t **opt, uint8_t cmd, uint32_t val) {
uint8_t *o = *opt;
*o++ = cmd;
*o++ = 4;
*o++ = val >> 24;
*o++ = val >> 16;
*o++ = val >> 8;
*o++ = val;
*opt = o;
}

static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *src_addr, u16_t src_port) {
dhcp_server_t *d = arg;
(void)upcb;
(void)src_addr;
(void)src_port;

// This is around 548 bytes
dhcp_msg_t dhcp_msg;

#define DHCP_MIN_SIZE (240 + 3)
if (p->tot_len < DHCP_MIN_SIZE) {
goto ignore_request;
}

size_t len = pbuf_copy_partial(p, &dhcp_msg, sizeof(dhcp_msg), 0);
if (len < DHCP_MIN_SIZE) {
goto ignore_request;
}

dhcp_msg.op = DHCPOFFER;
memcpy(&dhcp_msg.yiaddr, &d->ip.addr, 4);

uint8_t *opt = (uint8_t*)&dhcp_msg.options;
opt += 4; // assume magic cookie: 99, 130, 83, 99

switch (opt[2]) {
case DHCPDISCOVER: {
int yi = DHCPS_MAX_IP;
for (int i = 0; i < DHCPS_MAX_IP; ++i) {
if (memcmp(d->lease[i].mac, dhcp_msg.chaddr, MAC_LEN) == 0) {
// MAC match, use this IP address
yi = i;
break;
}
if (yi == DHCPS_MAX_IP) {
// Look for a free IP address
if (memcmp(d->lease[i].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) {
// IP available
yi = i;
}
uint32_t expiry = d->lease[i].expiry << 16 | 0xffff;
if ((int32_t)(expiry - mp_hal_ticks_ms()) < 0) {
// IP expired, reuse it
memset(d->lease[i].mac, 0, MAC_LEN);
yi = i;
}
}
}
if (yi == DHCPS_MAX_IP) {
// No more IP addresses left
goto ignore_request;
}
dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi;
opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPOFFER);
break;
}

case DHCPREQUEST: {
uint8_t *o = opt_find(opt, DHCP_OPT_REQUESTED_IP);
if (o == NULL) {
// Should be NACK
goto ignore_request;
}
if (memcmp(o + 2, &d->ip.addr, 3) != 0) {
// Should be NACK
goto ignore_request;
}
uint8_t yi = o[5] - DHCPS_BASE_IP;
if (yi >= DHCPS_MAX_IP) {
// Should be NACK
goto ignore_request;
}
if (memcmp(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN) == 0) {
// MAC match, ok to use this IP address
} else if (memcmp(d->lease[yi].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) {
// IP unused, ok to use this IP address
memcpy(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN);
} else {
// IP already in use
// Should be NACK
goto ignore_request;
}
d->lease[yi].expiry = (mp_hal_ticks_ms() + DEFAULT_LEASE_TIME_S * 1000) >> 16;
dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi;
opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPACK);
printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n",
dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5],
dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]);
break;
}

default:
goto ignore_request;
}

opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, &d->ip.addr);
opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, &d->nm.addr);
opt_write_n(&opt, DHCP_OPT_ROUTER, 4, &d->ip.addr); // aka gateway; can have mulitple addresses
opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have mulitple addresses
opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S);
*opt++ = DHCP_OPT_END;
dhcp_socket_sendto(&d->udp, &dhcp_msg, opt - (uint8_t*)&dhcp_msg, 0xffffffff, PORT_DHCP_CLIENT);

ignore_request:
pbuf_free(p);
}

void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm) {
ip_addr_copy(d->ip, *ip);
ip_addr_copy(d->nm, *nm);
memset(d->lease, 0, sizeof(d->lease));
if (dhcp_socket_new_dgram(&d->udp, d, dhcp_server_process) != 0) {
return;
}
dhcp_socket_bind(&d->udp, 0, PORT_DHCP_SERVER);
}

#endif // MICROPY_PY_LWIP
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy