Skip to content

rp2: micropython.schedule() thread safety #10690

Open
@peterhinch

Description

@peterhinch

The canonical use for micropython.schedule() is to enable a hard ISR to schedule a "soft" ISR which has GIL protection. For this to occur the "soft" code must run on the same core (0) as the main program.

In the following script the main program and the hard ISR run on core 0 while soft_isr runs on core 1. If soft_isr were to access shared data there would be a risk of corruption, for example if it accessed a global while the globals dict was being re-hashed.

The problem is that user code is running on another core under circumstances in which this would not be expected.

import micropython
import _thread
import time
from machine import Pin, mem32

pout = Pin(16, Pin.OUT)  # Link these pins
ipin = Pin(17, Pin.IN)

def pcore(s):
    print(f'{s} CPU core: {mem32[0xd0000000]} thread: {_thread.get_ident()}')

def isr(_):
    print(mem32[0xd0000000])
    micropython.schedule(soft_isr, None)

ipin.irq(handler=isr, hard=True)

def soft_isr(_):  # Scheduled by hard ISR
    pcore('soft')

def busy():
    while True:
        time.sleep(1)
        pcore('thread')

_thread.start_new_thread(busy, ())
pcore('main')
while True:
    pout(not pout())
    time.sleep_ms(200)

Outcome:

<irq>
main CPU core: 0 thread: 537095120
0
soft CPU core: 1 thread: 536912624
0
soft CPU core: 1 thread: 536912624
0
soft CPU core: 1 thread: 536912624
0
soft CPU core: 1 thread: 536912624
0
soft CPU core: 1 thread: 536912624
thread CPU core: 1 thread: 536912624
0
soft CPU core: 1 thread: 536912624
0

This arose from discussion #10638

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions