Skip to content

Commit

Permalink
rp2/mpnetworkport: Convert network task scheduling to use PendSV IRQ.
Browse files Browse the repository at this point in the history
It is more reliable and scales better when more components need it.

Work done in collaboration with Graham Sanderson and Peter Harper.

Signed-off-by: Damien George <damien@micropython.org>
  • Loading branch information
dpgeorge committed Jun 30, 2022
1 parent 7cdad05 commit c001cfa
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 47 deletions.
2 changes: 2 additions & 0 deletions ports/rp2/CMakeLists.txt
Expand Up @@ -111,6 +111,7 @@ set(MICROPY_SOURCE_PORT
mphalport.c
mpnetworkport.c
mpthreadport.c
pendsv.c
rp2_flash.c
rp2_pio.c
tusb_port.c
Expand Down Expand Up @@ -141,6 +142,7 @@ set(MICROPY_SOURCE_QSTR
)

set(PICO_SDK_COMPONENTS
cmsis_core
hardware_adc
hardware_base
hardware_clocks
Expand Down
60 changes: 13 additions & 47 deletions ports/rp2/mpnetworkport.c
Expand Up @@ -26,6 +26,7 @@

#include "py/runtime.h"
#include "py/mphal.h"
#include "pendsv.h"

#if MICROPY_PY_LWIP

Expand All @@ -36,77 +37,42 @@
#define LWIP_TICK_RATE_MS 64

static alarm_id_t lwip_alarm_id = -1;
static bool lwip_can_poll = true;
static bool lwip_poll_pending = false;

#if MICROPY_PY_NETWORK_WIZNET5K
static bool wiznet_poll_pending = false;

void wiznet5k_poll(void);
void wiznet5k_deinit(void);

void wiznet5k_try_poll(void) {
pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll);
}
#endif

u32_t sys_now(void) {
// Used by LwIP
return mp_hal_ticks_ms();
}

STATIC uint32_t lwip_poll(void) {
STATIC void lwip_poll(void) {
// Run the lwIP internal updates
sys_check_timeouts();

return MAX(5, MIN(sys_timeouts_sleeptime(), LWIP_TICK_RATE_MS));
}

void lwip_lock_acquire(void) {
lwip_can_poll = false;
// Prevent PendSV from running.
pendsv_suspend();
}

void lwip_lock_release(void) {
lwip_can_poll = false;
#if MICROPY_PY_NETWORK_WIZNET5K
if (wiznet_poll_pending) {
wiznet5k_poll();
wiznet_poll_pending = false;
}
#endif

if (lwip_poll_pending) {
lwip_poll();
lwip_poll_pending = false;
}
lwip_can_poll = true;
// Allow PendSV to run again.
pendsv_resume();
}

uint32_t lwip_try_poll(void) {
uint32_t ret = LWIP_TICK_RATE_MS;
if (lwip_can_poll) {
lwip_can_poll = false;
ret = lwip_poll();
lwip_can_poll = true;
} else {
lwip_poll_pending = true;
}
return ret;
}

#if MICROPY_PY_NETWORK_WIZNET5K
void wiznet5k_try_poll(void) {
if (lwip_can_poll) {
lwip_can_poll = false;
wiznet5k_poll();
lwip_can_poll = true;
} else {
wiznet_poll_pending = true;
}
}
#endif

STATIC int64_t alarm_callback(alarm_id_t id, void *user_data) {
pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, lwip_poll);
#if MICROPY_PY_NETWORK_WIZNET5K
wiznet5k_try_poll();
pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll);
#endif
return (int64_t)lwip_try_poll() * 1000;
return LWIP_TICK_RATE_MS * 1000;
}

void mod_network_lwip_init(void) {
Expand Down
70 changes: 70 additions & 0 deletions ports/rp2/pendsv.c
@@ -0,0 +1,70 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 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.
*/

#include <assert.h>
#include "pendsv.h"
#include "RP2040.h"

static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
static int pendsv_lock;

void pendsv_suspend(void) {
pendsv_lock++;
}

void pendsv_resume(void) {
pendsv_lock--;
assert(pendsv_lock >= 0);
// Run pendsv if needed. Find an entry with a dispatch and call pendsv dispatch
// with it. If pendsv runs it will service all slots.
int count = PENDSV_DISPATCH_NUM_SLOTS;
while (count--) {
if (pendsv_dispatch_table[count]) {
pendsv_schedule_dispatch(count, pendsv_dispatch_table[count]);
break;
}
}
}

void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
assert(pendsv_lock >= 0);
pendsv_dispatch_table[slot] = f;
if (pendsv_lock == 0) {
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
}

// PendSV interrupt handler to perform background processing.
void PendSV_Handler(void) {
assert(pendsv_lock == 0);
for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) {
if (pendsv_dispatch_table[i] != NULL) {
pendsv_dispatch_t f = pendsv_dispatch_table[i];
pendsv_dispatch_table[i] = NULL;
f();
}
}
}
49 changes: 49 additions & 0 deletions ports/rp2/pendsv.h
@@ -0,0 +1,49 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 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.
*/
#ifndef MICROPY_INCLUDED_RP2_PENDSV_H
#define MICROPY_INCLUDED_RP2_PENDSV_H

#include <stddef.h>

enum {
#if MICROPY_PY_LWIP
PENDSV_DISPATCH_LWIP,
#endif
#if MICROPY_PY_NETWORK_WIZNET5K
PENDSV_DISPATCH_WIZNET,
#endif
PENDSV_DISPATCH_MAX
};

#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX

typedef void (*pendsv_dispatch_t)(void);

void pendsv_suspend(void);
void pendsv_resume(void);
void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f);

#endif // MICROPY_INCLUDED_RP2_PENDSV_H

0 comments on commit c001cfa

Please sign in to comment.