Skip to content

rp2: Dual core code behaves non-deterministically driving UART #7977

Closed

Description

@peterhinch

The following runs for a while before the other thread on the second core stops UART output. The other thread continues to run, as evidenced by the incrementing g value. In my actual application I have seen UART output restart and stop again periodically, sometimes over times of many seconds.

Similar code with multiple uasyncio tasks outputting to the UART but running on one core works as expected.

If you change things in the code such as the type of g, the presence or absence of the sleep_ms(20) or whether foo is started, the UART behaviour changes but not in a way which seems to make sense. In every case the code runs: it is only the UART output which is unexpected.

import _thread
from time import sleep_ms
import uasyncio as asyncio
from machine import UART

u = UART(0, 1_000_000)

lock = _thread.allocate_lock()
g = 1.0  # 'a'

def other():
    global g
    while True:
        u.write('A')
        lock.acquire()
        # Proof of code running.
        g += 0.1  #  g += 'a'
        sleep_ms(20)  # Commenting-out can alter behaviour
        lock.release()
        u.write('a')
        sleep_ms(100)

async def foo():
    while True:
        u.write(b'\x40')  # @
        await asyncio.sleep_ms(0)
        u.write(b'\x60')  # `
        await asyncio.sleep_ms(0)

async def main():
    u.write('z')
    asyncio.create_task(foo())  # Commenting-out can alter behaviour
    _thread.start_new_thread(other, ())
    while True:
        u.write('B')
        while lock.locked():
            await asyncio.sleep_ms(0)
        lock.acquire()
        print(g)
        lock.release()
        u.write('b')
        await asyncio.sleep_ms(103)

asyncio.run(main())

Activity

  1. peterhinch commented on Nov 7, 2021

    @peterhinch
    ContributorAuthor

    I ran two tests to try to narrow this down.

    1. Changed the interface to SPI: result was the same with erratic behaviour.
    2. Ran on a Pyboard using _thread (and UART): this worked perfectly.

    So the issue seems specific to dual core running on RP2.

    On the suggestion of Mike Teachman I tried using the lock to protect every UART write (on the theory that re-entrancy might be occurring). This did not fix the problem.

  2. peterhinch commented on Feb 19, 2022

    @peterhinch
    ContributorAuthor

    Fixed by #8310!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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